ffmpeg / libavformat / dsicin.c @ 4dcde00c
History | View | Annotate | Download (6.48 KB)
1 | 72450e50 | Baptiste Coudurier | /*
|
---|---|---|---|
2 | * Delphine Software International CIN File Demuxer
|
||
3 | * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
|
||
4 | *
|
||
5 | 2912e87a | Mans Rullgard | * This file is part of Libav.
|
6 | 72450e50 | Baptiste Coudurier | *
|
7 | 2912e87a | Mans Rullgard | * Libav is free software; you can redistribute it and/or
|
8 | 72450e50 | Baptiste Coudurier | * 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.
|
||
11 | *
|
||
12 | 2912e87a | Mans Rullgard | * Libav is distributed in the hope that it will be useful,
|
13 | 72450e50 | Baptiste Coudurier | * 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.
|
||
16 | *
|
||
17 | * You should have received a copy of the GNU Lesser General Public
|
||
18 | 2912e87a | Mans Rullgard | * License along with Libav; if not, write to the Free Software
|
19 | 72450e50 | Baptiste Coudurier | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20 | */
|
||
21 | |||
22 | /**
|
||
23 | ba87f080 | Diego Biurrun | * @file
|
24 | 72450e50 | Baptiste Coudurier | * Delphine Software International CIN file demuxer
|
25 | */
|
||
26 | |||
27 | 6a5d31ac | Diego Biurrun | #include "libavutil/intreadwrite.h" |
28 | 72450e50 | Baptiste Coudurier | #include "avformat.h" |
29 | |||
30 | |||
31 | typedef struct CinFileHeader { |
||
32 | int video_frame_size;
|
||
33 | int video_frame_width;
|
||
34 | int video_frame_height;
|
||
35 | int audio_frequency;
|
||
36 | int audio_bits;
|
||
37 | int audio_stereo;
|
||
38 | int audio_frame_size;
|
||
39 | } CinFileHeader; |
||
40 | |||
41 | typedef struct CinFrameHeader { |
||
42 | int audio_frame_type;
|
||
43 | int video_frame_type;
|
||
44 | int pal_colors_count;
|
||
45 | int audio_frame_size;
|
||
46 | int video_frame_size;
|
||
47 | } CinFrameHeader; |
||
48 | |||
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;
|
||
57 | } CinDemuxContext; |
||
58 | |||
59 | |||
60 | static int cin_probe(AVProbeData *p) |
||
61 | { |
||
62 | /* header starts with this special marker */
|
||
63 | fead30d4 | Alex Beregszaszi | if (AV_RL32(&p->buf[0]) != 0x55AA0000) |
64 | 72450e50 | Baptiste Coudurier | return 0; |
65 | |||
66 | /* for accuracy, check some header field values */
|
||
67 | fead30d4 | Alex Beregszaszi | if (AV_RL32(&p->buf[12]) != 22050 || p->buf[16] != 16 || p->buf[17] != 0) |
68 | 72450e50 | Baptiste Coudurier | return 0; |
69 | |||
70 | return AVPROBE_SCORE_MAX;
|
||
71 | } |
||
72 | |||
73 | ae628ec1 | Anton Khirnov | static int cin_read_file_header(CinDemuxContext *cin, AVIOContext *pb) { |
74 | 72450e50 | Baptiste Coudurier | CinFileHeader *hdr = &cin->file_header; |
75 | |||
76 | b7effd4e | Anton Khirnov | if (avio_rl32(pb) != 0x55AA0000) |
77 | 72450e50 | Baptiste Coudurier | return AVERROR_INVALIDDATA;
|
78 | |||
79 | b7effd4e | Anton Khirnov | hdr->video_frame_size = avio_rl32(pb); |
80 | hdr->video_frame_width = avio_rl16(pb); |
||
81 | hdr->video_frame_height = avio_rl16(pb); |
||
82 | hdr->audio_frequency = avio_rl32(pb); |
||
83 | hdr->audio_bits = avio_r8(pb); |
||
84 | hdr->audio_stereo = avio_r8(pb); |
||
85 | hdr->audio_frame_size = avio_rl16(pb); |
||
86 | 72450e50 | Baptiste Coudurier | |
87 | if (hdr->audio_frequency != 22050 || hdr->audio_bits != 16 || hdr->audio_stereo != 0) |
||
88 | return AVERROR_INVALIDDATA;
|
||
89 | |||
90 | return 0; |
||
91 | } |
||
92 | |||
93 | static int cin_read_header(AVFormatContext *s, AVFormatParameters *ap) |
||
94 | { |
||
95 | int rc;
|
||
96 | e4141433 | Nicholas Tung | CinDemuxContext *cin = s->priv_data; |
97 | 72450e50 | Baptiste Coudurier | CinFileHeader *hdr = &cin->file_header; |
98 | ae628ec1 | Anton Khirnov | AVIOContext *pb = s->pb; |
99 | 72450e50 | Baptiste Coudurier | AVStream *st; |
100 | |||
101 | rc = cin_read_file_header(cin, pb); |
||
102 | if (rc)
|
||
103 | return rc;
|
||
104 | |||
105 | cin->video_stream_pts = 0;
|
||
106 | cin->audio_stream_pts = 0;
|
||
107 | cin->audio_buffer_size = 0;
|
||
108 | |||
109 | /* initialize the video decoder stream */
|
||
110 | st = av_new_stream(s, 0);
|
||
111 | if (!st)
|
||
112 | 769e10f0 | Panagiotis Issaris | return AVERROR(ENOMEM);
|
113 | 72450e50 | Baptiste Coudurier | |
114 | av_set_pts_info(st, 32, 1, 12); |
||
115 | cin->video_stream_index = st->index; |
||
116 | 72415b2a | Stefano Sabatini | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
117 | 72450e50 | Baptiste Coudurier | 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; |
||
121 | |||
122 | /* initialize the audio decoder stream */
|
||
123 | st = av_new_stream(s, 0);
|
||
124 | if (!st)
|
||
125 | 769e10f0 | Panagiotis Issaris | return AVERROR(ENOMEM);
|
126 | 72450e50 | Baptiste Coudurier | |
127 | av_set_pts_info(st, 32, 1, 22050); |
||
128 | cin->audio_stream_index = st->index; |
||
129 | 72415b2a | Stefano Sabatini | st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
130 | 72450e50 | Baptiste Coudurier | 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 | dd1c8f3e | Luca Abeni | 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; |
||
137 | 72450e50 | Baptiste Coudurier | |
138 | return 0; |
||
139 | } |
||
140 | |||
141 | ae628ec1 | Anton Khirnov | static int cin_read_frame_header(CinDemuxContext *cin, AVIOContext *pb) { |
142 | 72450e50 | Baptiste Coudurier | CinFrameHeader *hdr = &cin->frame_header; |
143 | |||
144 | b7effd4e | Anton Khirnov | hdr->video_frame_type = avio_r8(pb); |
145 | hdr->audio_frame_type = avio_r8(pb); |
||
146 | hdr->pal_colors_count = avio_rl16(pb); |
||
147 | hdr->video_frame_size = avio_rl32(pb); |
||
148 | hdr->audio_frame_size = avio_rl32(pb); |
||
149 | 72450e50 | Baptiste Coudurier | |
150 | 3e68b3ba | Anton Khirnov | if (pb->eof_reached || pb->error)
|
151 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
152 | 72450e50 | Baptiste Coudurier | |
153 | b7effd4e | Anton Khirnov | if (avio_rl32(pb) != 0xAA55AA55) |
154 | 72450e50 | Baptiste Coudurier | return AVERROR_INVALIDDATA;
|
155 | |||
156 | return 0; |
||
157 | } |
||
158 | |||
159 | static int cin_read_packet(AVFormatContext *s, AVPacket *pkt) |
||
160 | { |
||
161 | e4141433 | Nicholas Tung | CinDemuxContext *cin = s->priv_data; |
162 | ae628ec1 | Anton Khirnov | AVIOContext *pb = s->pb; |
163 | 72450e50 | Baptiste Coudurier | CinFrameHeader *hdr = &cin->frame_header; |
164 | int rc, palette_type, pkt_size;
|
||
165 | df2235a1 | Vitor Sessak | int ret;
|
166 | 72450e50 | Baptiste Coudurier | |
167 | if (cin->audio_buffer_size == 0) { |
||
168 | rc = cin_read_frame_header(cin, pb); |
||
169 | if (rc)
|
||
170 | return rc;
|
||
171 | |||
172 | if ((int16_t)hdr->pal_colors_count < 0) { |
||
173 | hdr->pal_colors_count = -(int16_t)hdr->pal_colors_count; |
||
174 | palette_type = 1;
|
||
175 | } else {
|
||
176 | palette_type = 0;
|
||
177 | } |
||
178 | |||
179 | /* palette and video packet */
|
||
180 | pkt_size = (palette_type + 3) * hdr->pal_colors_count + hdr->video_frame_size;
|
||
181 | |||
182 | df2235a1 | Vitor Sessak | ret = av_new_packet(pkt, 4 + pkt_size);
|
183 | if (ret < 0) |
||
184 | return ret;
|
||
185 | 72450e50 | Baptiste Coudurier | |
186 | pkt->stream_index = cin->video_stream_index; |
||
187 | pkt->pts = cin->video_stream_pts++; |
||
188 | |||
189 | pkt->data[0] = palette_type;
|
||
190 | pkt->data[1] = hdr->pal_colors_count & 0xFF; |
||
191 | pkt->data[2] = hdr->pal_colors_count >> 8; |
||
192 | pkt->data[3] = hdr->video_frame_type;
|
||
193 | |||
194 | b7effd4e | Anton Khirnov | ret = avio_read(pb, &pkt->data[4], pkt_size);
|
195 | df2235a1 | Vitor Sessak | if (ret < 0) { |
196 | av_free_packet(pkt); |
||
197 | return ret;
|
||
198 | } |
||
199 | if (ret < pkt_size)
|
||
200 | av_shrink_packet(pkt, 4 + ret);
|
||
201 | 72450e50 | Baptiste Coudurier | |
202 | /* sound buffer will be processed on next read_packet() call */
|
||
203 | cin->audio_buffer_size = hdr->audio_frame_size; |
||
204 | return 0; |
||
205 | } |
||
206 | |||
207 | /* audio packet */
|
||
208 | df2235a1 | Vitor Sessak | ret = av_get_packet(pb, pkt, cin->audio_buffer_size); |
209 | if (ret < 0) |
||
210 | return ret;
|
||
211 | 72450e50 | Baptiste Coudurier | |
212 | pkt->stream_index = cin->audio_stream_index; |
||
213 | pkt->pts = cin->audio_stream_pts; |
||
214 | cin->audio_stream_pts += cin->audio_buffer_size * 2 / cin->file_header.audio_frame_size;
|
||
215 | cin->audio_buffer_size = 0;
|
||
216 | return 0; |
||
217 | } |
||
218 | |||
219 | c6610a21 | Diego Elio Pettenò | AVInputFormat ff_dsicin_demuxer = { |
220 | 72450e50 | Baptiste Coudurier | "dsicin",
|
221 | bde15e74 | Stefano Sabatini | NULL_IF_CONFIG_SMALL("Delphine Software International CIN format"),
|
222 | 72450e50 | Baptiste Coudurier | sizeof(CinDemuxContext),
|
223 | cin_probe, |
||
224 | cin_read_header, |
||
225 | cin_read_packet, |
||
226 | }; |