2 * Delphine Software International CIN File Demuxer
3 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Delphine Software International CIN file demuxer
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/intreadwrite.h"
31 #include "avio_internal.h"
34 typedef struct CinFileHeader
{
36 int video_frame_width
;
37 int video_frame_height
;
44 typedef struct CinFrameHeader
{
52 typedef struct CinDemuxContext
{
53 int audio_stream_index
;
54 int video_stream_index
;
55 CinFileHeader file_header
;
56 int64_t audio_stream_pts
;
57 int64_t video_stream_pts
;
58 CinFrameHeader frame_header
;
59 int audio_buffer_size
;
63 static int cin_probe(AVProbeData
*p
)
65 /* header starts with this special marker */
66 if (AV_RL32(&p
->buf
[0]) != 0x55AA0000)
69 /* for accuracy, check some header field values */
70 if (AV_RL32(&p
->buf
[12]) != 22050 || p
->buf
[16] != 16 || p
->buf
[17] != 0)
73 return AVPROBE_SCORE_MAX
;
76 static int cin_read_file_header(CinDemuxContext
*cin
, AVIOContext
*pb
) {
77 CinFileHeader
*hdr
= &cin
->file_header
;
79 if (avio_rl32(pb
) != 0x55AA0000)
80 return AVERROR_INVALIDDATA
;
82 hdr
->video_frame_size
= avio_rl32(pb
);
83 hdr
->video_frame_width
= avio_rl16(pb
);
84 hdr
->video_frame_height
= avio_rl16(pb
);
85 hdr
->audio_frequency
= avio_rl32(pb
);
86 hdr
->audio_bits
= avio_r8(pb
);
87 hdr
->audio_stereo
= avio_r8(pb
);
88 hdr
->audio_frame_size
= avio_rl16(pb
);
90 if (hdr
->audio_frequency
!= 22050 || hdr
->audio_bits
!= 16 || hdr
->audio_stereo
!= 0)
91 return AVERROR_INVALIDDATA
;
96 static int cin_read_header(AVFormatContext
*s
)
99 CinDemuxContext
*cin
= s
->priv_data
;
100 CinFileHeader
*hdr
= &cin
->file_header
;
101 AVIOContext
*pb
= s
->pb
;
104 rc
= cin_read_file_header(cin
, pb
);
108 cin
->video_stream_pts
= 0;
109 cin
->audio_stream_pts
= 0;
110 cin
->audio_buffer_size
= 0;
112 /* initialize the video decoder stream */
113 st
= avformat_new_stream(s
, NULL
);
115 return AVERROR(ENOMEM
);
117 avpriv_set_pts_info(st
, 32, 1, 12);
118 cin
->video_stream_index
= st
->index
;
119 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
120 st
->codec
->codec_id
= AV_CODEC_ID_DSICINVIDEO
;
121 st
->codec
->codec_tag
= 0; /* no fourcc */
122 st
->codec
->width
= hdr
->video_frame_width
;
123 st
->codec
->height
= hdr
->video_frame_height
;
125 /* initialize the audio decoder stream */
126 st
= avformat_new_stream(s
, NULL
);
128 return AVERROR(ENOMEM
);
130 avpriv_set_pts_info(st
, 32, 1, 22050);
131 cin
->audio_stream_index
= st
->index
;
132 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
133 st
->codec
->codec_id
= AV_CODEC_ID_DSICINAUDIO
;
134 st
->codec
->codec_tag
= 0; /* no tag */
135 st
->codec
->channels
= 1;
136 st
->codec
->channel_layout
= AV_CH_LAYOUT_MONO
;
137 st
->codec
->sample_rate
= 22050;
138 st
->codec
->bits_per_coded_sample
= 8;
139 st
->codec
->bit_rate
= st
->codec
->sample_rate
* st
->codec
->bits_per_coded_sample
* st
->codec
->channels
;
144 static int cin_read_frame_header(CinDemuxContext
*cin
, AVIOContext
*pb
) {
145 CinFrameHeader
*hdr
= &cin
->frame_header
;
147 hdr
->video_frame_type
= avio_r8(pb
);
148 hdr
->audio_frame_type
= avio_r8(pb
);
149 hdr
->pal_colors_count
= avio_rl16(pb
);
150 hdr
->video_frame_size
= avio_rl32(pb
);
151 hdr
->audio_frame_size
= avio_rl32(pb
);
153 if (avio_feof(pb
) || pb
->error
)
156 if (avio_rl32(pb
) != 0xAA55AA55)
157 return AVERROR_INVALIDDATA
;
158 if (hdr
->video_frame_size
< 0 || hdr
->audio_frame_size
< 0)
159 return AVERROR_INVALIDDATA
;
164 static int cin_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
166 CinDemuxContext
*cin
= s
->priv_data
;
167 AVIOContext
*pb
= s
->pb
;
168 CinFrameHeader
*hdr
= &cin
->frame_header
;
169 int rc
, palette_type
, pkt_size
;
172 if (cin
->audio_buffer_size
== 0) {
173 rc
= cin_read_frame_header(cin
, pb
);
177 if ((int16_t)hdr
->pal_colors_count
< 0) {
178 hdr
->pal_colors_count
= -(int16_t)hdr
->pal_colors_count
;
184 /* palette and video packet */
185 pkt_size
= (palette_type
+ 3) * hdr
->pal_colors_count
+ hdr
->video_frame_size
;
187 pkt_size
= ffio_limit(pb
, pkt_size
);
189 ret
= av_new_packet(pkt
, 4 + pkt_size
);
193 pkt
->stream_index
= cin
->video_stream_index
;
194 pkt
->pts
= cin
->video_stream_pts
++;
196 pkt
->data
[0] = palette_type
;
197 pkt
->data
[1] = hdr
->pal_colors_count
& 0xFF;
198 pkt
->data
[2] = hdr
->pal_colors_count
>> 8;
199 pkt
->data
[3] = hdr
->video_frame_type
;
201 ret
= avio_read(pb
, &pkt
->data
[4], pkt_size
);
207 av_shrink_packet(pkt
, 4 + ret
);
209 /* sound buffer will be processed on next read_packet() call */
210 cin
->audio_buffer_size
= hdr
->audio_frame_size
;
215 ret
= av_get_packet(pb
, pkt
, cin
->audio_buffer_size
);
219 pkt
->stream_index
= cin
->audio_stream_index
;
220 pkt
->pts
= cin
->audio_stream_pts
;
221 pkt
->duration
= cin
->audio_buffer_size
- (pkt
->pts
== 0);
222 cin
->audio_stream_pts
+= pkt
->duration
;
223 cin
->audio_buffer_size
= 0;
227 AVInputFormat ff_dsicin_demuxer
= {
229 .long_name
= NULL_IF_CONFIG_SMALL("Delphine Software International CIN"),
230 .priv_data_size
= sizeof(CinDemuxContext
),
231 .read_probe
= cin_probe
,
232 .read_header
= cin_read_header
,
233 .read_packet
= cin_read_packet
,