1 /*
2 * ARMovie/RPL demuxer
3 * Copyright (c) 2007 Christian Ohm, 2008 Eli Friedman
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <inttypes.h>
23 #include <stdlib.h>
24
29
30 #define RPL_SIGNATURE "ARMovie\x0A"
31 #define RPL_SIGNATURE_SIZE 8
32
33 /** 256 is arbitrary, but should be big enough for any reasonable file. */
34 #define RPL_LINE_LENGTH 256
35
37 {
39 return 0;
40
42 }
43
45 // RPL header data
47
48 // Stream position data
53
55 {
56 int i;
57 for (i = 0; i < bufsize - 1; i++) {
59 if (b == 0)
60 break;
61 if (b == '\n') {
62 line[i] = '0円';
64 }
66 }
67 line[i] = '0円';
68 return -1;
69 }
70
72 {
73 unsigned long result = 0;
74 for (; *line>='0' && *line<='9'; line++) {
75 if (result > (0x7FFFFFFF - 9) / 10)
76 *error = -1;
77 result = 10 * result + *line - '0';
78 }
79 *endptr = line;
80 return result;
81 }
82
84 {
86 const char *endptr;
87 *error |=
read_line(pb, line,
sizeof(line));
88 return read_int(line, &endptr, error);
89 }
90
91 /** Parsing for fps, which can be a fraction. Unfortunately,
92 * the spec for the header leaves out a lot of details,
93 * so this is mostly guessing.
94 */
96 {
97 int64_t num, den = 1;
100 if (*line == '.')
101 line++;
102 for (; *line>='0' && *line<='9'; line++) {
103 // Truncate any numerator too large to fit into an int64_t
104 if (num > (INT64_MAX - 9) / 10 || den > INT64_MAX / 10)
105 break;
106 num = 10 * num + *line - '0';
107 den *= 10;
108 }
109 if (!num)
110 *error = -1;
112 return result;
113 }
114
116 {
120 int total_audio_size;
121 int error = 0;
122
123 uint32_t i;
124
125 int32_t audio_format, chunk_catalog_offset, number_of_chunks;
127
129
130 // The header for RPL/ARMovie files is 21 lines of text
131 // containing the various header fields. The fields are always
132 // in the same order, and other text besides the first
133 // number usually isn't important.
134 // (The spec says that there exists some significance
135 // for the text in a few cases; samples needed.)
136 error |=
read_line(pb, line,
sizeof(line));
// ARMovie
137 error |=
read_line(pb, line,
sizeof(line));
// movie name
139 error |=
read_line(pb, line,
sizeof(line));
// date/copyright
141 error |=
read_line(pb, line,
sizeof(line));
// author and other
143
144 // video headers
146 if (!vst)
153 error |=
read_line(pb, line,
sizeof(line));
// video frames per second
156
157 // Figure out the video codec
159 #if 0
160 case 122:
162 break;
163 #endif
164 case 124:
166 // The header is wrong here, at least sometimes
168 break;
169 case 130:
171 break;
172 default:
176 }
177
178 // Audio headers
179
180 // ARMovie supports multiple audio tracks; I don't have any
181 // samples, though. This code will ignore additional tracks.
183 if (audio_format) {
185 if (!ast)
188 ast->codec->codec_tag = audio_format;
190 ast->codec->channels =
read_line_and_int(pb, &error);
// number of audio channels
191 ast->codec->bits_per_coded_sample =
read_line_and_int(pb, &error);
// audio bits per sample
192 // At least one sample uses 0 for ADPCM, which is really 4 bits
193 // per sample.
194 if (ast->codec->bits_per_coded_sample == 0)
195 ast->codec->bits_per_coded_sample = 4;
196
197 ast->codec->bit_rate = ast->codec->sample_rate *
198 ast->codec->bits_per_coded_sample *
199 ast->codec->channels;
200
202 switch (audio_format) {
203 case 1:
204 if (ast->codec->bits_per_coded_sample == 16) {
205 // 16-bit audio is always signed
207 break;
208 }
209 // There are some other formats listed as legal per the spec;
210 // samples needed.
211 break;
212 case 101:
213 if (ast->codec->bits_per_coded_sample == 8) {
214 // The samples with this kind of audio that I have
215 // are all unsigned.
217 break;
218 } else if (ast->codec->bits_per_coded_sample == 4) {
220 break;
221 }
222 break;
223 }
226 audio_format);
228 } else {
229 for (i = 0; i < 3; i++)
230 error |=
read_line(pb, line,
sizeof(line));
231 }
232
236 "Don't know how to split frames for video format %i. "
238
239 number_of_chunks =
read_line_and_int(pb, &error);
// number of chunks in the file
240 // The number in the header is actually the index of the last chunk.
241 number_of_chunks++;
242
243 error |=
read_line(pb, line,
sizeof(line));
// "even" chunk size in bytes
244 error |=
read_line(pb, line,
sizeof(line));
// "odd" chunk size in bytes
245 chunk_catalog_offset = // offset of the "chunk catalog"
247 error |=
read_line(pb, line,
sizeof(line));
// offset to "helpful" sprite
248 error |=
read_line(pb, line,
sizeof(line));
// size of "helpful" sprite
249 error |=
read_line(pb, line,
sizeof(line));
// offset to key frame list
250
251 // Read the index
252 avio_seek(pb, chunk_catalog_offset, SEEK_SET);
253 total_audio_size = 0;
254 for (i = 0; !error && i < number_of_chunks; i++) {
255 int64_t
offset, video_size, audio_size;
256 error |=
read_line(pb, line,
sizeof(line));
257 if (3 != sscanf(line, "%"SCNd64" , %"SCNd64" ; %"SCNd64,
258 &offset, &video_size, &audio_size)) {
259 error = -1;
260 continue;
261 }
264 if (ast)
266 audio_size, audio_size * 8, 0);
267 total_audio_size += audio_size * 8;
268 }
269
270 if (error)
return AVERROR(EIO);
271
272 return 0;
273 }
274
276 {
282
286 }
287
289
292
294
298
301 // We have to split Escape 124 frames because there are
302 // multiple frames per chunk in Escape 124 samples.
304
309
311 if (ret != frame_size) {
314 }
318
323 }
324 } else {
326 if (ret != index_entry->
size) {
329 }
330
332 // frames_per_chunk should always be one here; the header
333 // parsing will warn if it isn't.
335 } else {
336 // All the audio codecs supported in this container
337 // (at least so far) are constant-bitrate.
339 }
343 }
344
345 // None of the Escape formats have keyframes, and the ADPCM
346 // format used doesn't have keyframes.
349
351 }
352
360 };