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
23 * @file libavformat/dsicin.c
24 * Delphine Software International CIN file demuxer
27 #include "libavutil/intreadwrite.h"
31 typedef struct CinFileHeader
{
33 int video_frame_width
;
34 int video_frame_height
;
41 typedef struct CinFrameHeader
{
49 typedef struct CinDemuxContext
{
50 int audio_stream_index
;
51 int video_stream_index
;
52 CinFileHeader file_header
;
53 int64_t audio_stream_pts
;
54 int64_t video_stream_pts
;
55 CinFrameHeader frame_header
;
56 int audio_buffer_size
;
60 static int cin_probe(AVProbeData
*p
)
62 /* header starts with this special marker */
63 if (AV_RL32(&p
->buf
[0]) != 0x55AA0000)
66 /* for accuracy, check some header field values */
67 if (AV_RL32(&p
->buf
[12]) != 22050 || p
->buf
[16] != 16 || p
->buf
[17] != 0)
70 return AVPROBE_SCORE_MAX
;
73 static int cin_read_file_header(CinDemuxContext
*cin
, ByteIOContext
*pb
) {
74 CinFileHeader
*hdr
= &cin
->file_header
;
76 if (get_le32(pb
) != 0x55AA0000)
77 return AVERROR_INVALIDDATA
;
79 hdr
->video_frame_size
= get_le32(pb
);
80 hdr
->video_frame_width
= get_le16(pb
);
81 hdr
->video_frame_height
= get_le16(pb
);
82 hdr
->audio_frequency
= get_le32(pb
);
83 hdr
->audio_bits
= get_byte(pb
);
84 hdr
->audio_stereo
= get_byte(pb
);
85 hdr
->audio_frame_size
= get_le16(pb
);
87 if (hdr
->audio_frequency
!= 22050 || hdr
->audio_bits
!= 16 || hdr
->audio_stereo
!= 0)
88 return AVERROR_INVALIDDATA
;
93 static int cin_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
96 CinDemuxContext
*cin
= s
->priv_data
;
97 CinFileHeader
*hdr
= &cin
->file_header
;
98 ByteIOContext
*pb
= s
->pb
;
101 rc
= cin_read_file_header(cin
, pb
);
105 cin
->video_stream_pts
= 0;
106 cin
->audio_stream_pts
= 0;
107 cin
->audio_buffer_size
= 0;
109 /* initialize the video decoder stream */
110 st
= av_new_stream(s
, 0);
112 return AVERROR(ENOMEM
);
114 av_set_pts_info(st
, 32, 1, 12);
115 cin
->video_stream_index
= st
->index
;
116 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
117 st
->codec
->codec_id
= CODEC_ID_DSICINVIDEO
;
118 st
->codec
->codec_tag
= 0; /* no fourcc */
119 st
->codec
->width
= hdr
->video_frame_width
;
120 st
->codec
->height
= hdr
->video_frame_height
;
122 /* initialize the audio decoder stream */
123 st
= av_new_stream(s
, 0);
125 return AVERROR(ENOMEM
);
127 av_set_pts_info(st
, 32, 1, 22050);
128 cin
->audio_stream_index
= st
->index
;
129 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
130 st
->codec
->codec_id
= CODEC_ID_DSICINAUDIO
;
131 st
->codec
->codec_tag
= 0; /* no tag */
132 st
->codec
->channels
= 1;
133 st
->codec
->sample_rate
= 22050;
134 st
->codec
->bits_per_coded_sample
= 16;
135 st
->codec
->bit_rate
= st
->codec
->sample_rate
* st
->codec
->bits_per_coded_sample
* st
->codec
->channels
;
136 st
->codec
->block_align
= st
->codec
->channels
* st
->codec
->bits_per_coded_sample
;
141 static int cin_read_frame_header(CinDemuxContext
*cin
, ByteIOContext
*pb
) {
142 CinFrameHeader
*hdr
= &cin
->frame_header
;
144 hdr
->video_frame_type
= get_byte(pb
);
145 hdr
->audio_frame_type
= get_byte(pb
);
146 hdr
->pal_colors_count
= get_le16(pb
);
147 hdr
->video_frame_size
= get_le32(pb
);
148 hdr
->audio_frame_size
= get_le32(pb
);
150 if (url_feof(pb
) || url_ferror(pb
))
153 if (get_le32(pb
) != 0xAA55AA55)
154 return AVERROR_INVALIDDATA
;
159 static int cin_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
161 CinDemuxContext
*cin
= s
->priv_data
;
162 ByteIOContext
*pb
= s
->pb
;
163 CinFrameHeader
*hdr
= &cin
->frame_header
;
164 int rc
, palette_type
, pkt_size
;
166 if (cin
->audio_buffer_size
== 0) {
167 rc
= cin_read_frame_header(cin
, pb
);
171 if ((int16_t)hdr
->pal_colors_count
< 0) {
172 hdr
->pal_colors_count
= -(int16_t)hdr
->pal_colors_count
;
178 /* palette and video packet */
179 pkt_size
= (palette_type
+ 3) * hdr
->pal_colors_count
+ hdr
->video_frame_size
;
181 if (av_new_packet(pkt
, 4 + pkt_size
))
182 return AVERROR(ENOMEM
);
184 pkt
->stream_index
= cin
->video_stream_index
;
185 pkt
->pts
= cin
->video_stream_pts
++;
187 pkt
->data
[0] = palette_type
;
188 pkt
->data
[1] = hdr
->pal_colors_count
& 0xFF;
189 pkt
->data
[2] = hdr
->pal_colors_count
>> 8;
190 pkt
->data
[3] = hdr
->video_frame_type
;
192 if (get_buffer(pb
, &pkt
->data
[4], pkt_size
) != pkt_size
)
195 /* sound buffer will be processed on next read_packet() call */
196 cin
->audio_buffer_size
= hdr
->audio_frame_size
;
201 if (av_new_packet(pkt
, cin
->audio_buffer_size
))
202 return AVERROR(ENOMEM
);
204 pkt
->stream_index
= cin
->audio_stream_index
;
205 pkt
->pts
= cin
->audio_stream_pts
;
206 cin
->audio_stream_pts
+= cin
->audio_buffer_size
* 2 / cin
->file_header
.audio_frame_size
;
208 if (get_buffer(pb
, pkt
->data
, cin
->audio_buffer_size
) != cin
->audio_buffer_size
)
211 cin
->audio_buffer_size
= 0;
215 AVInputFormat dsicin_demuxer
= {
217 NULL_IF_CONFIG_SMALL("Delphine Software International CIN format"),
218 sizeof(CinDemuxContext
),