yading@11
|
1 /*
|
yading@11
|
2 * GXF demuxer.
|
yading@11
|
3 * Copyright (c) 2006 Reimar Doeffinger
|
yading@11
|
4 *
|
yading@11
|
5 * This file is part of FFmpeg.
|
yading@11
|
6 *
|
yading@11
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
9 * License as published by the Free Software Foundation; either
|
yading@11
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
11 *
|
yading@11
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
15 * Lesser General Public License for more details.
|
yading@11
|
16 *
|
yading@11
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
20 */
|
yading@11
|
21
|
yading@11
|
22 #include "libavutil/channel_layout.h"
|
yading@11
|
23 #include "libavutil/common.h"
|
yading@11
|
24 #include "avformat.h"
|
yading@11
|
25 #include "internal.h"
|
yading@11
|
26 #include "gxf.h"
|
yading@11
|
27 #include "libavcodec/mpeg12data.h"
|
yading@11
|
28
|
yading@11
|
29 struct gxf_stream_info {
|
yading@11
|
30 int64_t first_field;
|
yading@11
|
31 int64_t last_field;
|
yading@11
|
32 AVRational frames_per_second;
|
yading@11
|
33 int32_t fields_per_frame;
|
yading@11
|
34 int64_t track_aux_data;
|
yading@11
|
35 };
|
yading@11
|
36
|
yading@11
|
37 /**
|
yading@11
|
38 * @brief parse gxf timecode and add it to metadata
|
yading@11
|
39 */
|
yading@11
|
40 static int add_timecode_metadata(AVDictionary **pm, const char *key, uint32_t timecode, int fields_per_frame)
|
yading@11
|
41 {
|
yading@11
|
42 char tmp[128];
|
yading@11
|
43 int field = timecode & 0xff;
|
yading@11
|
44 int frame = fields_per_frame ? field / fields_per_frame : field;
|
yading@11
|
45 int second = (timecode >> 8) & 0xff;
|
yading@11
|
46 int minute = (timecode >> 16) & 0xff;
|
yading@11
|
47 int hour = (timecode >> 24) & 0x1f;
|
yading@11
|
48 int drop = (timecode >> 29) & 1;
|
yading@11
|
49 // bit 30: color_frame, unused
|
yading@11
|
50 // ignore invalid time code
|
yading@11
|
51 if (timecode >> 31)
|
yading@11
|
52 return 0;
|
yading@11
|
53 snprintf(tmp, sizeof(tmp), "%02d:%02d:%02d%c%02d",
|
yading@11
|
54 hour, minute, second, drop ? ';' : ':', frame);
|
yading@11
|
55 return av_dict_set(pm, key, tmp, 0);
|
yading@11
|
56 }
|
yading@11
|
57
|
yading@11
|
58 /**
|
yading@11
|
59 * @brief parses a packet header, extracting type and length
|
yading@11
|
60 * @param pb AVIOContext to read header from
|
yading@11
|
61 * @param type detected packet type is stored here
|
yading@11
|
62 * @param length detected packet length, excluding header is stored here
|
yading@11
|
63 * @return 0 if header not found or contains invalid data, 1 otherwise
|
yading@11
|
64 */
|
yading@11
|
65 static int parse_packet_header(AVIOContext *pb, GXFPktType *type, int *length) {
|
yading@11
|
66 if (avio_rb32(pb))
|
yading@11
|
67 return 0;
|
yading@11
|
68 if (avio_r8(pb) != 1)
|
yading@11
|
69 return 0;
|
yading@11
|
70 *type = avio_r8(pb);
|
yading@11
|
71 *length = avio_rb32(pb);
|
yading@11
|
72 if ((*length >> 24) || *length < 16)
|
yading@11
|
73 return 0;
|
yading@11
|
74 *length -= 16;
|
yading@11
|
75 if (avio_rb32(pb))
|
yading@11
|
76 return 0;
|
yading@11
|
77 if (avio_r8(pb) != 0xe1)
|
yading@11
|
78 return 0;
|
yading@11
|
79 if (avio_r8(pb) != 0xe2)
|
yading@11
|
80 return 0;
|
yading@11
|
81 return 1;
|
yading@11
|
82 }
|
yading@11
|
83
|
yading@11
|
84 /**
|
yading@11
|
85 * @brief check if file starts with a PKT_MAP header
|
yading@11
|
86 */
|
yading@11
|
87 static int gxf_probe(AVProbeData *p) {
|
yading@11
|
88 static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
|
yading@11
|
89 static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
|
yading@11
|
90 if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
|
yading@11
|
91 !memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
|
yading@11
|
92 return AVPROBE_SCORE_MAX;
|
yading@11
|
93 return 0;
|
yading@11
|
94 }
|
yading@11
|
95
|
yading@11
|
96 /**
|
yading@11
|
97 * @brief gets the stream index for the track with the specified id, creates new
|
yading@11
|
98 * stream if not found
|
yading@11
|
99 * @param id id of stream to find / add
|
yading@11
|
100 * @param format stream format identifier
|
yading@11
|
101 */
|
yading@11
|
102 static int get_sindex(AVFormatContext *s, int id, int format) {
|
yading@11
|
103 int i;
|
yading@11
|
104 AVStream *st = NULL;
|
yading@11
|
105 i = ff_find_stream_index(s, id);
|
yading@11
|
106 if (i >= 0)
|
yading@11
|
107 return i;
|
yading@11
|
108 st = avformat_new_stream(s, NULL);
|
yading@11
|
109 if (!st)
|
yading@11
|
110 return AVERROR(ENOMEM);
|
yading@11
|
111 st->id = id;
|
yading@11
|
112 switch (format) {
|
yading@11
|
113 case 3:
|
yading@11
|
114 case 4:
|
yading@11
|
115 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
116 st->codec->codec_id = AV_CODEC_ID_MJPEG;
|
yading@11
|
117 break;
|
yading@11
|
118 case 13:
|
yading@11
|
119 case 15:
|
yading@11
|
120 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
121 st->codec->codec_id = AV_CODEC_ID_DVVIDEO;
|
yading@11
|
122 break;
|
yading@11
|
123 case 14:
|
yading@11
|
124 case 16:
|
yading@11
|
125 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
126 st->codec->codec_id = AV_CODEC_ID_DVVIDEO;
|
yading@11
|
127 break;
|
yading@11
|
128 case 11:
|
yading@11
|
129 case 12:
|
yading@11
|
130 case 20:
|
yading@11
|
131 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
132 st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO;
|
yading@11
|
133 st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
|
yading@11
|
134 break;
|
yading@11
|
135 case 22:
|
yading@11
|
136 case 23:
|
yading@11
|
137 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
138 st->codec->codec_id = AV_CODEC_ID_MPEG1VIDEO;
|
yading@11
|
139 st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
|
yading@11
|
140 break;
|
yading@11
|
141 case 9:
|
yading@11
|
142 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
yading@11
|
143 st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
|
yading@11
|
144 st->codec->channels = 1;
|
yading@11
|
145 st->codec->channel_layout = AV_CH_LAYOUT_MONO;
|
yading@11
|
146 st->codec->sample_rate = 48000;
|
yading@11
|
147 st->codec->bit_rate = 3 * 1 * 48000 * 8;
|
yading@11
|
148 st->codec->block_align = 3 * 1;
|
yading@11
|
149 st->codec->bits_per_coded_sample = 24;
|
yading@11
|
150 break;
|
yading@11
|
151 case 10:
|
yading@11
|
152 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
yading@11
|
153 st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
|
yading@11
|
154 st->codec->channels = 1;
|
yading@11
|
155 st->codec->channel_layout = AV_CH_LAYOUT_MONO;
|
yading@11
|
156 st->codec->sample_rate = 48000;
|
yading@11
|
157 st->codec->bit_rate = 2 * 1 * 48000 * 8;
|
yading@11
|
158 st->codec->block_align = 2 * 1;
|
yading@11
|
159 st->codec->bits_per_coded_sample = 16;
|
yading@11
|
160 break;
|
yading@11
|
161 case 17:
|
yading@11
|
162 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
yading@11
|
163 st->codec->codec_id = AV_CODEC_ID_AC3;
|
yading@11
|
164 st->codec->channels = 2;
|
yading@11
|
165 st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
|
yading@11
|
166 st->codec->sample_rate = 48000;
|
yading@11
|
167 break;
|
yading@11
|
168 // timecode tracks:
|
yading@11
|
169 case 7:
|
yading@11
|
170 case 8:
|
yading@11
|
171 case 24:
|
yading@11
|
172 st->codec->codec_type = AVMEDIA_TYPE_DATA;
|
yading@11
|
173 st->codec->codec_id = AV_CODEC_ID_NONE;
|
yading@11
|
174 break;
|
yading@11
|
175 default:
|
yading@11
|
176 st->codec->codec_type = AVMEDIA_TYPE_UNKNOWN;
|
yading@11
|
177 st->codec->codec_id = AV_CODEC_ID_NONE;
|
yading@11
|
178 break;
|
yading@11
|
179 }
|
yading@11
|
180 return s->nb_streams - 1;
|
yading@11
|
181 }
|
yading@11
|
182
|
yading@11
|
183 /**
|
yading@11
|
184 * @brief filters out interesting tags from material information.
|
yading@11
|
185 * @param len length of tag section, will be adjusted to contain remaining bytes
|
yading@11
|
186 * @param si struct to store collected information into
|
yading@11
|
187 */
|
yading@11
|
188 static void gxf_material_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
|
yading@11
|
189 si->first_field = AV_NOPTS_VALUE;
|
yading@11
|
190 si->last_field = AV_NOPTS_VALUE;
|
yading@11
|
191 while (*len >= 2) {
|
yading@11
|
192 GXFMatTag tag = avio_r8(pb);
|
yading@11
|
193 int tlen = avio_r8(pb);
|
yading@11
|
194 *len -= 2;
|
yading@11
|
195 if (tlen > *len)
|
yading@11
|
196 return;
|
yading@11
|
197 *len -= tlen;
|
yading@11
|
198 if (tlen == 4) {
|
yading@11
|
199 uint32_t value = avio_rb32(pb);
|
yading@11
|
200 if (tag == MAT_FIRST_FIELD)
|
yading@11
|
201 si->first_field = value;
|
yading@11
|
202 else if (tag == MAT_LAST_FIELD)
|
yading@11
|
203 si->last_field = value;
|
yading@11
|
204 } else
|
yading@11
|
205 avio_skip(pb, tlen);
|
yading@11
|
206 }
|
yading@11
|
207 }
|
yading@11
|
208
|
yading@11
|
209 static const AVRational frame_rate_tab[] = {
|
yading@11
|
210 { 60, 1},
|
yading@11
|
211 {60000, 1001},
|
yading@11
|
212 { 50, 1},
|
yading@11
|
213 { 30, 1},
|
yading@11
|
214 {30000, 1001},
|
yading@11
|
215 { 25, 1},
|
yading@11
|
216 { 24, 1},
|
yading@11
|
217 {24000, 1001},
|
yading@11
|
218 { 0, 0},
|
yading@11
|
219 };
|
yading@11
|
220
|
yading@11
|
221 /**
|
yading@11
|
222 * @brief convert fps tag value to AVRational fps
|
yading@11
|
223 * @param fps fps value from tag
|
yading@11
|
224 * @return fps as AVRational, or 0 / 0 if unknown
|
yading@11
|
225 */
|
yading@11
|
226 static AVRational fps_tag2avr(int32_t fps) {
|
yading@11
|
227 if (fps < 1 || fps > 9) fps = 9;
|
yading@11
|
228 return frame_rate_tab[fps - 1];
|
yading@11
|
229 }
|
yading@11
|
230
|
yading@11
|
231 /**
|
yading@11
|
232 * @brief convert UMF attributes flags to AVRational fps
|
yading@11
|
233 * @param flags UMF flags to convert
|
yading@11
|
234 * @return fps as AVRational, or 0 / 0 if unknown
|
yading@11
|
235 */
|
yading@11
|
236 static AVRational fps_umf2avr(uint32_t flags) {
|
yading@11
|
237 static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
|
yading@11
|
238 {25, 1}, {30000, 1001}};
|
yading@11
|
239 int idx = av_log2((flags & 0x7c0) >> 6);
|
yading@11
|
240 return map[idx];
|
yading@11
|
241 }
|
yading@11
|
242
|
yading@11
|
243 /**
|
yading@11
|
244 * @brief filters out interesting tags from track information.
|
yading@11
|
245 * @param len length of tag section, will be adjusted to contain remaining bytes
|
yading@11
|
246 * @param si struct to store collected information into
|
yading@11
|
247 */
|
yading@11
|
248 static void gxf_track_tags(AVIOContext *pb, int *len, struct gxf_stream_info *si) {
|
yading@11
|
249 si->frames_per_second = (AVRational){0, 0};
|
yading@11
|
250 si->fields_per_frame = 0;
|
yading@11
|
251 si->track_aux_data = 0x80000000;
|
yading@11
|
252 while (*len >= 2) {
|
yading@11
|
253 GXFTrackTag tag = avio_r8(pb);
|
yading@11
|
254 int tlen = avio_r8(pb);
|
yading@11
|
255 *len -= 2;
|
yading@11
|
256 if (tlen > *len)
|
yading@11
|
257 return;
|
yading@11
|
258 *len -= tlen;
|
yading@11
|
259 if (tlen == 4) {
|
yading@11
|
260 uint32_t value = avio_rb32(pb);
|
yading@11
|
261 if (tag == TRACK_FPS)
|
yading@11
|
262 si->frames_per_second = fps_tag2avr(value);
|
yading@11
|
263 else if (tag == TRACK_FPF && (value == 1 || value == 2))
|
yading@11
|
264 si->fields_per_frame = value;
|
yading@11
|
265 } else if (tlen == 8 && tag == TRACK_AUX)
|
yading@11
|
266 si->track_aux_data = avio_rl64(pb);
|
yading@11
|
267 else
|
yading@11
|
268 avio_skip(pb, tlen);
|
yading@11
|
269 }
|
yading@11
|
270 }
|
yading@11
|
271
|
yading@11
|
272 /**
|
yading@11
|
273 * @brief read index from FLT packet into stream 0 av_index
|
yading@11
|
274 */
|
yading@11
|
275 static void gxf_read_index(AVFormatContext *s, int pkt_len) {
|
yading@11
|
276 AVIOContext *pb = s->pb;
|
yading@11
|
277 AVStream *st;
|
yading@11
|
278 uint32_t fields_per_map = avio_rl32(pb);
|
yading@11
|
279 uint32_t map_cnt = avio_rl32(pb);
|
yading@11
|
280 int i;
|
yading@11
|
281 pkt_len -= 8;
|
yading@11
|
282 if ((s->flags & AVFMT_FLAG_IGNIDX) || !s->streams) {
|
yading@11
|
283 avio_skip(pb, pkt_len);
|
yading@11
|
284 return;
|
yading@11
|
285 }
|
yading@11
|
286 st = s->streams[0];
|
yading@11
|
287 if (map_cnt > 1000) {
|
yading@11
|
288 av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt);
|
yading@11
|
289 map_cnt = 1000;
|
yading@11
|
290 }
|
yading@11
|
291 if (pkt_len < 4 * map_cnt) {
|
yading@11
|
292 av_log(s, AV_LOG_ERROR, "invalid index length\n");
|
yading@11
|
293 avio_skip(pb, pkt_len);
|
yading@11
|
294 return;
|
yading@11
|
295 }
|
yading@11
|
296 pkt_len -= 4 * map_cnt;
|
yading@11
|
297 av_add_index_entry(st, 0, 0, 0, 0, 0);
|
yading@11
|
298 for (i = 0; i < map_cnt; i++)
|
yading@11
|
299 av_add_index_entry(st, (uint64_t)avio_rl32(pb) * 1024,
|
yading@11
|
300 i * (uint64_t)fields_per_map + 1, 0, 0, 0);
|
yading@11
|
301 avio_skip(pb, pkt_len);
|
yading@11
|
302 }
|
yading@11
|
303
|
yading@11
|
304 static int gxf_header(AVFormatContext *s) {
|
yading@11
|
305 AVIOContext *pb = s->pb;
|
yading@11
|
306 GXFPktType pkt_type;
|
yading@11
|
307 int map_len;
|
yading@11
|
308 int len;
|
yading@11
|
309 AVRational main_timebase = {0, 0};
|
yading@11
|
310 struct gxf_stream_info *si = s->priv_data;
|
yading@11
|
311 int i;
|
yading@11
|
312 if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
|
yading@11
|
313 av_log(s, AV_LOG_ERROR, "map packet not found\n");
|
yading@11
|
314 return 0;
|
yading@11
|
315 }
|
yading@11
|
316 map_len -= 2;
|
yading@11
|
317 if (avio_r8(pb) != 0x0e0 || avio_r8(pb) != 0xff) {
|
yading@11
|
318 av_log(s, AV_LOG_ERROR, "unknown version or invalid map preamble\n");
|
yading@11
|
319 return 0;
|
yading@11
|
320 }
|
yading@11
|
321 map_len -= 2;
|
yading@11
|
322 len = avio_rb16(pb); // length of material data section
|
yading@11
|
323 if (len > map_len) {
|
yading@11
|
324 av_log(s, AV_LOG_ERROR, "material data longer than map data\n");
|
yading@11
|
325 return 0;
|
yading@11
|
326 }
|
yading@11
|
327 map_len -= len;
|
yading@11
|
328 gxf_material_tags(pb, &len, si);
|
yading@11
|
329 avio_skip(pb, len);
|
yading@11
|
330 map_len -= 2;
|
yading@11
|
331 len = avio_rb16(pb); // length of track description
|
yading@11
|
332 if (len > map_len) {
|
yading@11
|
333 av_log(s, AV_LOG_ERROR, "track description longer than map data\n");
|
yading@11
|
334 return 0;
|
yading@11
|
335 }
|
yading@11
|
336 map_len -= len;
|
yading@11
|
337 while (len > 0) {
|
yading@11
|
338 int track_type, track_id, track_len;
|
yading@11
|
339 AVStream *st;
|
yading@11
|
340 int idx;
|
yading@11
|
341 len -= 4;
|
yading@11
|
342 track_type = avio_r8(pb);
|
yading@11
|
343 track_id = avio_r8(pb);
|
yading@11
|
344 track_len = avio_rb16(pb);
|
yading@11
|
345 len -= track_len;
|
yading@11
|
346 if (!(track_type & 0x80)) {
|
yading@11
|
347 av_log(s, AV_LOG_ERROR, "invalid track type %x\n", track_type);
|
yading@11
|
348 continue;
|
yading@11
|
349 }
|
yading@11
|
350 track_type &= 0x7f;
|
yading@11
|
351 if ((track_id & 0xc0) != 0xc0) {
|
yading@11
|
352 av_log(s, AV_LOG_ERROR, "invalid track id %x\n", track_id);
|
yading@11
|
353 continue;
|
yading@11
|
354 }
|
yading@11
|
355 track_id &= 0x3f;
|
yading@11
|
356 gxf_track_tags(pb, &track_len, si);
|
yading@11
|
357 // check for timecode tracks
|
yading@11
|
358 if (track_type == 7 || track_type == 8 || track_type == 24) {
|
yading@11
|
359 add_timecode_metadata(&s->metadata, "timecode",
|
yading@11
|
360 si->track_aux_data & 0xffffffff,
|
yading@11
|
361 si->fields_per_frame);
|
yading@11
|
362
|
yading@11
|
363 }
|
yading@11
|
364 avio_skip(pb, track_len);
|
yading@11
|
365
|
yading@11
|
366 idx = get_sindex(s, track_id, track_type);
|
yading@11
|
367 if (idx < 0) continue;
|
yading@11
|
368 st = s->streams[idx];
|
yading@11
|
369 if (!main_timebase.num || !main_timebase.den) {
|
yading@11
|
370 main_timebase.num = si->frames_per_second.den;
|
yading@11
|
371 main_timebase.den = si->frames_per_second.num * 2;
|
yading@11
|
372 }
|
yading@11
|
373 st->start_time = si->first_field;
|
yading@11
|
374 if (si->first_field != AV_NOPTS_VALUE && si->last_field != AV_NOPTS_VALUE)
|
yading@11
|
375 st->duration = si->last_field - si->first_field;
|
yading@11
|
376 }
|
yading@11
|
377 if (len < 0)
|
yading@11
|
378 av_log(s, AV_LOG_ERROR, "invalid track description length specified\n");
|
yading@11
|
379 if (map_len)
|
yading@11
|
380 avio_skip(pb, map_len);
|
yading@11
|
381 if (!parse_packet_header(pb, &pkt_type, &len)) {
|
yading@11
|
382 av_log(s, AV_LOG_ERROR, "sync lost in header\n");
|
yading@11
|
383 return -1;
|
yading@11
|
384 }
|
yading@11
|
385 if (pkt_type == PKT_FLT) {
|
yading@11
|
386 gxf_read_index(s, len);
|
yading@11
|
387 if (!parse_packet_header(pb, &pkt_type, &len)) {
|
yading@11
|
388 av_log(s, AV_LOG_ERROR, "sync lost in header\n");
|
yading@11
|
389 return -1;
|
yading@11
|
390 }
|
yading@11
|
391 }
|
yading@11
|
392 if (pkt_type == PKT_UMF) {
|
yading@11
|
393 if (len >= 0x39) {
|
yading@11
|
394 AVRational fps;
|
yading@11
|
395 len -= 0x39;
|
yading@11
|
396 avio_skip(pb, 5); // preamble
|
yading@11
|
397 avio_skip(pb, 0x30); // payload description
|
yading@11
|
398 fps = fps_umf2avr(avio_rl32(pb));
|
yading@11
|
399 if (!main_timebase.num || !main_timebase.den) {
|
yading@11
|
400 av_log(s, AV_LOG_WARNING, "No FPS track tag, using UMF fps tag."
|
yading@11
|
401 " This might give wrong results.\n");
|
yading@11
|
402 // this may not always be correct, but simply the best we can get
|
yading@11
|
403 main_timebase.num = fps.den;
|
yading@11
|
404 main_timebase.den = fps.num * 2;
|
yading@11
|
405 }
|
yading@11
|
406
|
yading@11
|
407 if (len >= 0x18) {
|
yading@11
|
408 len -= 0x18;
|
yading@11
|
409 avio_skip(pb, 0x10);
|
yading@11
|
410 add_timecode_metadata(&s->metadata, "timecode_at_mark_in",
|
yading@11
|
411 avio_rl32(pb), si->fields_per_frame);
|
yading@11
|
412 add_timecode_metadata(&s->metadata, "timecode_at_mark_out",
|
yading@11
|
413 avio_rl32(pb), si->fields_per_frame);
|
yading@11
|
414 }
|
yading@11
|
415 } else
|
yading@11
|
416 av_log(s, AV_LOG_INFO, "UMF packet too short\n");
|
yading@11
|
417 } else
|
yading@11
|
418 av_log(s, AV_LOG_INFO, "UMF packet missing\n");
|
yading@11
|
419 avio_skip(pb, len);
|
yading@11
|
420 // set a fallback value, 60000/1001 is specified for audio-only files
|
yading@11
|
421 // so use that regardless of why we do not know the video frame rate.
|
yading@11
|
422 if (!main_timebase.num || !main_timebase.den)
|
yading@11
|
423 main_timebase = (AVRational){1001, 60000};
|
yading@11
|
424 for (i = 0; i < s->nb_streams; i++) {
|
yading@11
|
425 AVStream *st = s->streams[i];
|
yading@11
|
426 avpriv_set_pts_info(st, 32, main_timebase.num, main_timebase.den);
|
yading@11
|
427 }
|
yading@11
|
428 return 0;
|
yading@11
|
429 }
|
yading@11
|
430
|
yading@11
|
431 #define READ_ONE() \
|
yading@11
|
432 { \
|
yading@11
|
433 if (!max_interval-- || url_feof(pb)) \
|
yading@11
|
434 goto out; \
|
yading@11
|
435 tmp = tmp << 8 | avio_r8(pb); \
|
yading@11
|
436 }
|
yading@11
|
437
|
yading@11
|
438 /**
|
yading@11
|
439 * @brief resync the stream on the next media packet with specified properties
|
yading@11
|
440 * @param max_interval how many bytes to search for matching packet at most
|
yading@11
|
441 * @param track track id the media packet must belong to, -1 for any
|
yading@11
|
442 * @param timestamp minimum timestamp (== field number) the packet must have, -1 for any
|
yading@11
|
443 * @return timestamp of packet found
|
yading@11
|
444 */
|
yading@11
|
445 static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
|
yading@11
|
446 uint32_t tmp;
|
yading@11
|
447 uint64_t last_pos;
|
yading@11
|
448 uint64_t last_found_pos = 0;
|
yading@11
|
449 int cur_track;
|
yading@11
|
450 int64_t cur_timestamp = AV_NOPTS_VALUE;
|
yading@11
|
451 int len;
|
yading@11
|
452 AVIOContext *pb = s->pb;
|
yading@11
|
453 GXFPktType type;
|
yading@11
|
454 tmp = avio_rb32(pb);
|
yading@11
|
455 start:
|
yading@11
|
456 while (tmp)
|
yading@11
|
457 READ_ONE();
|
yading@11
|
458 READ_ONE();
|
yading@11
|
459 if (tmp != 1)
|
yading@11
|
460 goto start;
|
yading@11
|
461 last_pos = avio_tell(pb);
|
yading@11
|
462 if (avio_seek(pb, -5, SEEK_CUR) < 0)
|
yading@11
|
463 goto out;
|
yading@11
|
464 if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
|
yading@11
|
465 if (avio_seek(pb, last_pos, SEEK_SET) < 0)
|
yading@11
|
466 goto out;
|
yading@11
|
467 goto start;
|
yading@11
|
468 }
|
yading@11
|
469 avio_r8(pb);
|
yading@11
|
470 cur_track = avio_r8(pb);
|
yading@11
|
471 cur_timestamp = avio_rb32(pb);
|
yading@11
|
472 last_found_pos = avio_tell(pb) - 16 - 6;
|
yading@11
|
473 if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
|
yading@11
|
474 if (avio_seek(pb, last_pos, SEEK_SET) >= 0)
|
yading@11
|
475 goto start;
|
yading@11
|
476 }
|
yading@11
|
477 out:
|
yading@11
|
478 if (last_found_pos)
|
yading@11
|
479 avio_seek(pb, last_found_pos, SEEK_SET);
|
yading@11
|
480 return cur_timestamp;
|
yading@11
|
481 }
|
yading@11
|
482
|
yading@11
|
483 static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
|
yading@11
|
484 AVIOContext *pb = s->pb;
|
yading@11
|
485 GXFPktType pkt_type;
|
yading@11
|
486 int pkt_len;
|
yading@11
|
487 struct gxf_stream_info *si = s->priv_data;
|
yading@11
|
488
|
yading@11
|
489 while (!pb->eof_reached) {
|
yading@11
|
490 AVStream *st;
|
yading@11
|
491 int track_type, track_id, ret;
|
yading@11
|
492 int field_nr, field_info, skip = 0;
|
yading@11
|
493 int stream_index;
|
yading@11
|
494 if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
|
yading@11
|
495 if (!url_feof(pb))
|
yading@11
|
496 av_log(s, AV_LOG_ERROR, "sync lost\n");
|
yading@11
|
497 return -1;
|
yading@11
|
498 }
|
yading@11
|
499 if (pkt_type == PKT_FLT) {
|
yading@11
|
500 gxf_read_index(s, pkt_len);
|
yading@11
|
501 continue;
|
yading@11
|
502 }
|
yading@11
|
503 if (pkt_type != PKT_MEDIA) {
|
yading@11
|
504 avio_skip(pb, pkt_len);
|
yading@11
|
505 continue;
|
yading@11
|
506 }
|
yading@11
|
507 if (pkt_len < 16) {
|
yading@11
|
508 av_log(s, AV_LOG_ERROR, "invalid media packet length\n");
|
yading@11
|
509 continue;
|
yading@11
|
510 }
|
yading@11
|
511 pkt_len -= 16;
|
yading@11
|
512 track_type = avio_r8(pb);
|
yading@11
|
513 track_id = avio_r8(pb);
|
yading@11
|
514 stream_index = get_sindex(s, track_id, track_type);
|
yading@11
|
515 if (stream_index < 0)
|
yading@11
|
516 return stream_index;
|
yading@11
|
517 st = s->streams[stream_index];
|
yading@11
|
518 field_nr = avio_rb32(pb);
|
yading@11
|
519 field_info = avio_rb32(pb);
|
yading@11
|
520 avio_rb32(pb); // "timeline" field number
|
yading@11
|
521 avio_r8(pb); // flags
|
yading@11
|
522 avio_r8(pb); // reserved
|
yading@11
|
523 if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE ||
|
yading@11
|
524 st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
|
yading@11
|
525 int first = field_info >> 16;
|
yading@11
|
526 int last = field_info & 0xffff; // last is exclusive
|
yading@11
|
527 int bps = av_get_bits_per_sample(st->codec->codec_id)>>3;
|
yading@11
|
528 if (first <= last && last*bps <= pkt_len) {
|
yading@11
|
529 avio_skip(pb, first*bps);
|
yading@11
|
530 skip = pkt_len - last*bps;
|
yading@11
|
531 pkt_len = (last-first)*bps;
|
yading@11
|
532 } else
|
yading@11
|
533 av_log(s, AV_LOG_ERROR, "invalid first and last sample values\n");
|
yading@11
|
534 }
|
yading@11
|
535 ret = av_get_packet(pb, pkt, pkt_len);
|
yading@11
|
536 if (skip)
|
yading@11
|
537 avio_skip(pb, skip);
|
yading@11
|
538 pkt->stream_index = stream_index;
|
yading@11
|
539 pkt->dts = field_nr;
|
yading@11
|
540
|
yading@11
|
541 //set duration manually for DV or else lavf misdetects the frame rate
|
yading@11
|
542 if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO)
|
yading@11
|
543 pkt->duration = si->fields_per_frame;
|
yading@11
|
544
|
yading@11
|
545 return ret;
|
yading@11
|
546 }
|
yading@11
|
547 return AVERROR_EOF;
|
yading@11
|
548 }
|
yading@11
|
549
|
yading@11
|
550 static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
|
yading@11
|
551 int res = 0;
|
yading@11
|
552 uint64_t pos;
|
yading@11
|
553 uint64_t maxlen = 100 * 1024 * 1024;
|
yading@11
|
554 AVStream *st = s->streams[0];
|
yading@11
|
555 int64_t start_time = s->streams[stream_index]->start_time;
|
yading@11
|
556 int64_t found;
|
yading@11
|
557 int idx;
|
yading@11
|
558 if (timestamp < start_time) timestamp = start_time;
|
yading@11
|
559 idx = av_index_search_timestamp(st, timestamp - start_time,
|
yading@11
|
560 AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
|
yading@11
|
561 if (idx < 0)
|
yading@11
|
562 return -1;
|
yading@11
|
563 pos = st->index_entries[idx].pos;
|
yading@11
|
564 if (idx < st->nb_index_entries - 2)
|
yading@11
|
565 maxlen = st->index_entries[idx + 2].pos - pos;
|
yading@11
|
566 maxlen = FFMAX(maxlen, 200 * 1024);
|
yading@11
|
567 res = avio_seek(s->pb, pos, SEEK_SET);
|
yading@11
|
568 if (res < 0)
|
yading@11
|
569 return res;
|
yading@11
|
570 found = gxf_resync_media(s, maxlen, -1, timestamp);
|
yading@11
|
571 if (FFABS(found - timestamp) > 4)
|
yading@11
|
572 return -1;
|
yading@11
|
573 return 0;
|
yading@11
|
574 }
|
yading@11
|
575
|
yading@11
|
576 static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
|
yading@11
|
577 int64_t *pos, int64_t pos_limit) {
|
yading@11
|
578 AVIOContext *pb = s->pb;
|
yading@11
|
579 int64_t res;
|
yading@11
|
580 if (avio_seek(pb, *pos, SEEK_SET) < 0)
|
yading@11
|
581 return AV_NOPTS_VALUE;
|
yading@11
|
582 res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
|
yading@11
|
583 *pos = avio_tell(pb);
|
yading@11
|
584 return res;
|
yading@11
|
585 }
|
yading@11
|
586
|
yading@11
|
587 AVInputFormat ff_gxf_demuxer = {
|
yading@11
|
588 .name = "gxf",
|
yading@11
|
589 .long_name = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"),
|
yading@11
|
590 .priv_data_size = sizeof(struct gxf_stream_info),
|
yading@11
|
591 .read_probe = gxf_probe,
|
yading@11
|
592 .read_header = gxf_header,
|
yading@11
|
593 .read_packet = gxf_packet,
|
yading@11
|
594 .read_seek = gxf_seek,
|
yading@11
|
595 .read_timestamp = gxf_read_timestamp,
|
yading@11
|
596 };
|