annotate rpl.c @ 3754:8d267b43eaba libavformat

Move malloc() down until after all initializations, so that the resource is only allocated if initialization worked. This means that on failure, we don't have to deallocate it.
author rbultje
date Sat, 23 Aug 2008 18:46:30 +0000
parents 7a0230981402
children 1d3d17de20ba
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3197
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
1 /*
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
2 * ARMovie/RPL demuxer
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
3 * Copyright (c) 2007 Christian Ohm, 2008 Eli Friedman
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
4 *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
5 * This file is part of FFmpeg.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
6 *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
11 *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
15 * Lesser General Public License for more details.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
16 *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
20 */
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
21
3286
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 3197
diff changeset
22 #include "libavutil/avstring.h"
3197
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
23 #include "avformat.h"
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
24 #include <stdlib.h>
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
25
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
26 #define RPL_SIGNATURE "ARMovie\x0A"
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
27 #define RPL_SIGNATURE_SIZE 8
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
28
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
29 /** 256 is arbitrary, but should be big enough for any reasonable file. */
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
30 #define RPL_LINE_LENGTH 256
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
31
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
32 static int rpl_probe(AVProbeData *p)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
33 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
34 if (memcmp(p->buf, RPL_SIGNATURE, RPL_SIGNATURE_SIZE))
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
35 return 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
36
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
37 return AVPROBE_SCORE_MAX;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
38 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
39
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
40 typedef struct RPLContext {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
41 // RPL header data
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
42 int32_t frames_per_chunk;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
43
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
44 // Stream position data
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
45 uint32_t chunk_number;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
46 uint32_t chunk_part;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
47 uint32_t frame_in_part;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
48 } RPLContext;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
49
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
50 static int read_line(ByteIOContext * pb, char* line, int bufsize)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
51 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
52 int i;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
53 for (i = 0; i < bufsize - 1; i++) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
54 int b = get_byte(pb);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
55 if (b == 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
56 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
57 if (b == '\n') {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
58 line[i] = '\0';
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
59 return 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
60 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
61 line[i] = b;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
62 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
63 line[i] = '\0';
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
64 return -1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
65 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
66
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
67 static int32_t read_int(const char* line, const char** endptr, int* error)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
68 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
69 unsigned long result = 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
70 for (; *line>='0' && *line<='9'; line++) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
71 if (result > (0x7FFFFFFF - 9) / 10)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
72 *error = -1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
73 result = 10 * result + *line - '0';
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
74 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
75 *endptr = line;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
76 return result;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
77 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
78
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
79 static int32_t read_line_and_int(ByteIOContext * pb, int* error)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
80 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
81 char line[RPL_LINE_LENGTH];
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
82 const char *endptr;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
83 *error |= read_line(pb, line, sizeof(line));
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
84 return read_int(line, &endptr, error);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
85 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
86
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
87 /** Parsing for fps, which can be a fraction. Unfortunately,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
88 * the spec for the header leaves out a lot of details,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
89 * so this is mostly guessing.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
90 */
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
91 static AVRational read_fps(const char* line, int* error)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
92 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
93 int64_t num, den = 1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
94 AVRational result;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
95 num = read_int(line, &line, error);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
96 if (*line == '.')
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
97 line++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
98 for (; *line>='0' && *line<='9'; line++) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
99 // Truncate any numerator too large to fit into an int64_t
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
100 if (num > (INT64_MAX - 9) / 10 || den > INT64_MAX / 10)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
101 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
102 num = 10 * num + *line - '0';
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
103 den *= 10;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
104 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
105 if (!num)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
106 *error = -1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
107 av_reduce(&result.num, &result.den, num, den, 0x7FFFFFFF);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
108 return result;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
109 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
110
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
111 static int rpl_read_header(AVFormatContext *s, AVFormatParameters *ap)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
112 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
113 ByteIOContext *pb = s->pb;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
114 RPLContext *rpl = s->priv_data;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
115 AVStream *vst = NULL, *ast = NULL;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
116 int total_audio_size;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
117 int error = 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
118
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
119 uint32_t i;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
120
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
121 int32_t audio_format, chunk_catalog_offset, number_of_chunks;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
122 AVRational fps;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
123
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
124 char line[RPL_LINE_LENGTH];
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
125
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
126 // The header for RPL/ARMovie files is 21 lines of text
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
127 // containing the various header fields. The fields are always
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
128 // in the same order, and other text besides the first
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
129 // number usually isn't important.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
130 // (The spec says that there exists some significance
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
131 // for the text in a few cases; samples needed.)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
132 error |= read_line(pb, line , sizeof(line )); // ARMovie
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
133 error |= read_line(pb, s->title , sizeof(s->title )); // movie name
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
134 error |= read_line(pb, s->copyright, sizeof(s->copyright)); // date/copyright
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
135 error |= read_line(pb, s->author , sizeof(s->author )); // author and other
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
136
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
137 // video headers
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
138 vst = av_new_stream(s, 0);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
139 if (!vst)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
140 return AVERROR(ENOMEM);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
141 vst->codec->codec_type = CODEC_TYPE_VIDEO;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
142 vst->codec->codec_tag = read_line_and_int(pb, &error); // video format
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
143 vst->codec->width = read_line_and_int(pb, &error); // video width
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
144 vst->codec->height = read_line_and_int(pb, &error); // video height
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
145 vst->codec->bits_per_sample = read_line_and_int(pb, &error); // video bits per sample
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
146 error |= read_line(pb, line, sizeof(line)); // video frames per second
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
147 fps = read_fps(line, &error);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
148 av_set_pts_info(vst, 32, fps.den, fps.num);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
149
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
150 // Figure out the video codec
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
151 switch (vst->codec->codec_tag) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
152 #if 0
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
153 case 122:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
154 vst->codec->codec_id = CODEC_ID_ESCAPE122;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
155 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
156 #endif
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
157 case 124:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
158 vst->codec->codec_id = CODEC_ID_ESCAPE124;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
159 // The header is wrong here, at least sometimes
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
160 vst->codec->bits_per_sample = 16;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
161 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
162 #if 0
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
163 case 130:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
164 vst->codec->codec_id = CODEC_ID_ESCAPE130;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
165 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
166 #endif
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
167 default:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
168 av_log(s, AV_LOG_WARNING,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
169 "RPL video format %i not supported yet!\n",
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
170 vst->codec->codec_tag);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
171 vst->codec->codec_id = CODEC_ID_NONE;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
172 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
173
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
174 // Audio headers
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
175
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
176 // ARMovie supports multiple audio tracks; I don't have any
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
177 // samples, though. This code will ignore additional tracks.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
178 audio_format = read_line_and_int(pb, &error); // audio format ID
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
179 if (audio_format) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
180 ast = av_new_stream(s, 0);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
181 if (!ast)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
182 return AVERROR(ENOMEM);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
183 ast->codec->codec_type = CODEC_TYPE_AUDIO;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
184 ast->codec->codec_tag = audio_format;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
185 ast->codec->sample_rate = read_line_and_int(pb, &error); // audio bitrate
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
186 ast->codec->channels = read_line_and_int(pb, &error); // number of audio channels
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
187 ast->codec->bits_per_sample = read_line_and_int(pb, &error); // audio bits per sample
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
188 // At least one sample uses 0 for ADPCM, which is really 4 bits
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
189 // per sample.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
190 if (ast->codec->bits_per_sample == 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
191 ast->codec->bits_per_sample = 4;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
192
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
193 ast->codec->bit_rate = ast->codec->sample_rate *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
194 ast->codec->bits_per_sample *
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
195 ast->codec->channels;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
196
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
197 ast->codec->codec_id = CODEC_ID_NONE;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
198 switch (audio_format) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
199 case 1:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
200 if (ast->codec->bits_per_sample == 16) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
201 // 16-bit audio is always signed
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
202 ast->codec->codec_id = CODEC_ID_PCM_S16LE;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
203 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
204 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
205 // There are some other formats listed as legal per the spec;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
206 // samples needed.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
207 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
208 case 101:
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
209 if (ast->codec->bits_per_sample == 8) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
210 // The samples with this kind of audio that I have
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
211 // are all unsigned.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
212 ast->codec->codec_id = CODEC_ID_PCM_U8;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
213 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
214 } else if (ast->codec->bits_per_sample == 4) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
215 ast->codec->codec_id = CODEC_ID_ADPCM_IMA_EA_SEAD;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
216 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
217 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
218 break;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
219 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
220 if (ast->codec->codec_id == CODEC_ID_NONE) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
221 av_log(s, AV_LOG_WARNING,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
222 "RPL audio format %i not supported yet!\n",
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
223 audio_format);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
224 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
225 av_set_pts_info(ast, 32, 1, ast->codec->bit_rate);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
226 } else {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
227 for (i = 0; i < 3; i++)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
228 error |= read_line(pb, line, sizeof(line));
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
229 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
230
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
231 rpl->frames_per_chunk = read_line_and_int(pb, &error); // video frames per chunk
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
232 if (rpl->frames_per_chunk > 1 && vst->codec->codec_tag != 124)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
233 av_log(s, AV_LOG_WARNING,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
234 "Don't know how to split frames for video format %i. "
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
235 "Video stream will be broken!\n", vst->codec->codec_tag);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
236
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
237 number_of_chunks = read_line_and_int(pb, &error); // number of chunks in the file
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
238 // The number in the header is actually the index of the last chunk.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
239 number_of_chunks++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
240
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
241 error |= read_line(pb, line, sizeof(line)); // "even" chunk size in bytes
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
242 error |= read_line(pb, line, sizeof(line)); // "odd" chunk size in bytes
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
243 chunk_catalog_offset = // offset of the "chunk catalog"
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
244 read_line_and_int(pb, &error); // (file index)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
245 error |= read_line(pb, line, sizeof(line)); // offset to "helpful" sprite
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
246 error |= read_line(pb, line, sizeof(line)); // size of "helpful" sprite
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
247 error |= read_line(pb, line, sizeof(line)); // offset to key frame list
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
248
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
249 // Read the index
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
250 url_fseek(pb, chunk_catalog_offset, SEEK_SET);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
251 total_audio_size = 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
252 for (i = 0; i < number_of_chunks; i++) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
253 int64_t offset, video_size, audio_size;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
254 error |= read_line(pb, line, sizeof(line));
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
255 if (3 != sscanf(line, "%"PRId64" , %"PRId64" ; %"PRId64,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
256 &offset, &video_size, &audio_size))
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
257 error = -1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
258 av_add_index_entry(vst, offset, i * rpl->frames_per_chunk,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
259 video_size, rpl->frames_per_chunk, 0);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
260 if (ast)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
261 av_add_index_entry(ast, offset + video_size, total_audio_size,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
262 audio_size, audio_size * 8, 0);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
263 total_audio_size += audio_size * 8;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
264 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
265
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
266 if (error) return AVERROR(EIO);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
267
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
268 return 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
269 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
270
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
271 static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
272 {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
273 RPLContext *rpl = s->priv_data;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
274 ByteIOContext *pb = s->pb;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
275 AVStream* stream;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
276 AVIndexEntry* index_entry;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
277 uint32_t ret;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
278
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
279 if (rpl->chunk_part == s->nb_streams) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
280 rpl->chunk_number++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
281 rpl->chunk_part = 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
282 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
283
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
284 stream = s->streams[rpl->chunk_part];
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
285
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
286 if (rpl->chunk_number >= stream->nb_index_entries)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
287 return -1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
288
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
289 index_entry = &stream->index_entries[rpl->chunk_number];
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
290
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
291 if (rpl->frame_in_part == 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
292 if (url_fseek(pb, index_entry->pos, SEEK_SET) < 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
293 return AVERROR(EIO);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
294
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
295 if (stream->codec->codec_type == CODEC_TYPE_VIDEO &&
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
296 stream->codec->codec_tag == 124) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
297 // We have to split Escape 124 frames because there are
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
298 // multiple frames per chunk in Escape 124 samples.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
299 uint32_t frame_size, frame_flags;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
300
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
301 frame_flags = get_le32(pb);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
302 frame_size = get_le32(pb);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
303 if (url_fseek(pb, -8, SEEK_CUR) < 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
304 return AVERROR(EIO);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
305
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
306 ret = av_get_packet(pb, pkt, frame_size);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
307 if (ret != frame_size) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
308 av_free_packet(pkt);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
309 return AVERROR(EIO);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
310 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
311 pkt->duration = 1;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
312 pkt->pts = index_entry->timestamp + rpl->frame_in_part;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
313 pkt->stream_index = rpl->chunk_part;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
314
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
315 rpl->frame_in_part++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
316 if (rpl->frame_in_part == rpl->frames_per_chunk) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
317 rpl->frame_in_part = 0;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
318 rpl->chunk_part++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
319 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
320 } else {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
321 ret = av_get_packet(pb, pkt, index_entry->size);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
322 if (ret != index_entry->size) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
323 av_free_packet(pkt);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
324 return AVERROR(EIO);
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
325 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
326
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
327 if (stream->codec->codec_type == CODEC_TYPE_VIDEO) {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
328 // frames_per_chunk should always be one here; the header
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
329 // parsing will warn if it isn't.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
330 pkt->duration = rpl->frames_per_chunk;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
331 } else {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
332 // All the audio codecs supported in this container
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
333 // (at least so far) are constant-bitrate.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
334 pkt->duration = ret * 8;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
335 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
336 pkt->pts = index_entry->timestamp;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
337 pkt->stream_index = rpl->chunk_part;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
338 rpl->chunk_part++;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
339 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
340
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
341 // None of the Escape formats have keyframes, and the ADPCM
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
342 // format used doesn't have keyframes.
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
343 if (rpl->chunk_number == 0 && rpl->frame_in_part == 0)
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
344 pkt->flags |= PKT_FLAG_KEY;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
345
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
346 return ret;
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
347 }
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
348
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
349 AVInputFormat rpl_demuxer = {
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
350 "rpl",
3424
7a0230981402 Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents: 3286
diff changeset
351 NULL_IF_CONFIG_SMALL("RPL/ARMovie format"),
3197
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
352 sizeof(RPLContext),
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
353 rpl_probe,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
354 rpl_read_header,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
355 rpl_read_packet,
e56c575b6717 ARMovie/RPL demuxer
superdump
parents:
diff changeset
356 };