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
30 typedef struct CinFileHeader
{
32 int video_frame_width
;
33 int video_frame_height
;
40 typedef struct CinFrameHeader
{
48 typedef struct CinDemuxContext
{
49 int audio_stream_index
;
50 int video_stream_index
;
51 CinFileHeader file_header
;
52 int64_t audio_stream_pts
;
53 int64_t video_stream_pts
;
54 CinFrameHeader frame_header
;
55 int audio_buffer_size
;
59 static int cin_probe(AVProbeData
*p
)
61 /* header starts with this special marker */
62 if (AV_RL32(&p
->buf
[0]) != 0x55AA0000)
65 /* for accuracy, check some header field values */
66 if (AV_RL32(&p
->buf
[12]) != 22050 || p
->buf
[16] != 16 || p
->buf
[17] != 0)
69 return AVPROBE_SCORE_MAX
;
72 static int cin_read_file_header(CinDemuxContext
*cin
, ByteIOContext
*pb
) {
73 CinFileHeader
*hdr
= &cin
->file_header
;
75 if (get_le32(pb
) != 0x55AA0000)
76 return AVERROR_INVALIDDATA
;
78 hdr
->video_frame_size
= get_le32(pb
);
79 hdr
->video_frame_width
= get_le16(pb
);
80 hdr
->video_frame_height
= get_le16(pb
);
81 hdr
->audio_frequency
= get_le32(pb
);
82 hdr
->audio_bits
= get_byte(pb
);
83 hdr
->audio_stereo
= get_byte(pb
);
84 hdr
->audio_frame_size
= get_le16(pb
);
86 if (hdr
->audio_frequency
!= 22050 || hdr
->audio_bits
!= 16 || hdr
->audio_stereo
!= 0)
87 return AVERROR_INVALIDDATA
;
92 static int cin_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
95 CinDemuxContext
*cin
= s
->priv_data
;
96 CinFileHeader
*hdr
= &cin
->file_header
;
97 ByteIOContext
*pb
= s
->pb
;
100 rc
= cin_read_file_header(cin
, pb
);
104 cin
->video_stream_pts
= 0;
105 cin
->audio_stream_pts
= 0;
106 cin
->audio_buffer_size
= 0;
108 /* initialize the video decoder stream */
109 st
= av_new_stream(s
, 0);
111 return AVERROR(ENOMEM
);
113 av_set_pts_info(st
, 32, 1, 12);
114 cin
->video_stream_index
= st
->index
;
115 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
116 st
->codec
->codec_id
= CODEC_ID_DSICINVIDEO
;
117 st
->codec
->codec_tag
= 0; /* no fourcc */
118 st
->codec
->width
= hdr
->video_frame_width
;
119 st
->codec
->height
= hdr
->video_frame_height
;
121 /* initialize the audio decoder stream */
122 st
= av_new_stream(s
, 0);
124 return AVERROR(ENOMEM
);
126 av_set_pts_info(st
, 32, 1, 22050);
127 cin
->audio_stream_index
= st
->index
;
128 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
129 st
->codec
->codec_id
= CODEC_ID_DSICINAUDIO
;
130 st
->codec
->codec_tag
= 0; /* no tag */
131 st
->codec
->channels
= 1;
132 st
->codec
->sample_rate
= 22050;
133 st
->codec
->bits_per_coded_sample
= 16;
134 st
->codec
->bit_rate
= st
->codec
->sample_rate
* st
->codec
->bits_per_coded_sample
* st
->codec
->channels
;
135 st
->codec
->block_align
= st
->codec
->channels
* st
->codec
->bits_per_coded_sample
;
140 static int cin_read_frame_header(CinDemuxContext
*cin
, ByteIOContext
*pb
) {
141 CinFrameHeader
*hdr
= &cin
->frame_header
;
143 hdr
->video_frame_type
= get_byte(pb
);
144 hdr
->audio_frame_type
= get_byte(pb
);
145 hdr
->pal_colors_count
= get_le16(pb
);
146 hdr
->video_frame_size
= get_le32(pb
);
147 hdr
->audio_frame_size
= get_le32(pb
);
149 if (url_feof(pb
) || url_ferror(pb
))
152 if (get_le32(pb
) != 0xAA55AA55)
153 return AVERROR_INVALIDDATA
;
158 static int cin_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
160 CinDemuxContext
*cin
= s
->priv_data
;
161 ByteIOContext
*pb
= s
->pb
;
162 CinFrameHeader
*hdr
= &cin
->frame_header
;
163 int rc
, palette_type
, pkt_size
;
165 if (cin
->audio_buffer_size
== 0) {
166 rc
= cin_read_frame_header(cin
, pb
);
170 if ((int16_t)hdr
->pal_colors_count
< 0) {
171 hdr
->pal_colors_count
= -(int16_t)hdr
->pal_colors_count
;
177 /* palette and video packet */
178 pkt_size
= (palette_type
+ 3) * hdr
->pal_colors_count
+ hdr
->video_frame_size
;
180 if (av_new_packet(pkt
, 4 + pkt_size
))
181 return AVERROR(ENOMEM
);
183 pkt
->stream_index
= cin
->video_stream_index
;
184 pkt
->pts
= cin
->video_stream_pts
++;
186 pkt
->data
[0] = palette_type
;
187 pkt
->data
[1] = hdr
->pal_colors_count
& 0xFF;
188 pkt
->data
[2] = hdr
->pal_colors_count
>> 8;
189 pkt
->data
[3] = hdr
->video_frame_type
;
191 if (get_buffer(pb
, &pkt
->data
[4], pkt_size
) != pkt_size
)
194 /* sound buffer will be processed on next read_packet() call */
195 cin
->audio_buffer_size
= hdr
->audio_frame_size
;
200 if (av_new_packet(pkt
, cin
->audio_buffer_size
))
201 return AVERROR(ENOMEM
);
203 pkt
->stream_index
= cin
->audio_stream_index
;
204 pkt
->pts
= cin
->audio_stream_pts
;
205 cin
->audio_stream_pts
+= cin
->audio_buffer_size
* 2 / cin
->file_header
.audio_frame_size
;
207 if (get_buffer(pb
, pkt
->data
, cin
->audio_buffer_size
) != cin
->audio_buffer_size
)
210 cin
->audio_buffer_size
= 0;
214 AVInputFormat dsicin_demuxer
= {
216 NULL_IF_CONFIG_SMALL("Delphine Software International CIN format"),
217 sizeof(CinDemuxContext
),