annotate gxf.c @ 5237:496723640f94 libavformat

Extend DV autodetection to also reliably detect single-frame DVs with a higher score that MAX/4. It checks that there are at least 10 DIF headers and at least one per 24000 bytes, and if so considers the file reliably detected as DV. Passes probetest, too.
author reimar
date Tue, 29 Sep 2009 10:12:18 +0000
parents 77e0c7511d41
children fcf809c679f2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
1 /*
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
2 * GXF demuxer.
4251
77e0c7511d41 cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents: 4098
diff changeset
3 * Copyright (c) 2006 Reimar Doeffinger
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
4 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
5 * This file is part of FFmpeg.
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
6 *
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
11 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
15 * Lesser General Public License for more details.
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
16 *
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1243
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
20 */
3286
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2771
diff changeset
21
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2771
diff changeset
22 #include "libavutil/common.h"
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
23 #include "avformat.h"
2282
47f5906c30cc replaces hardcoded values by the equivalent enum definitions
aurel
parents: 2274
diff changeset
24 #include "gxf.h"
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
25
4074
58051a1dc7ea Use "struct gxf_stream_info" instead of "st_info_t",
reimar
parents: 3939
diff changeset
26 struct gxf_stream_info {
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
27 int64_t first_field;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
28 int64_t last_field;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
29 AVRational frames_per_second;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
30 int32_t fields_per_frame;
4074
58051a1dc7ea Use "struct gxf_stream_info" instead of "st_info_t",
reimar
parents: 3939
diff changeset
31 };
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
32
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
33 /**
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
34 * \brief parses a packet header, extracting type and length
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
35 * \param pb ByteIOContext to read header from
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
36 * \param type detected packet type is stored here
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
37 * \param length detected packet length, excluding header is stored here
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
38 * \return 0 if header not found or contains invalid data, 1 otherwise
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
39 */
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
40 static int parse_packet_header(ByteIOContext *pb, GXFPktType *type, int *length) {
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
41 if (get_be32(pb))
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
42 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
43 if (get_byte(pb) != 1)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
44 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
45 *type = get_byte(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
46 *length = get_be32(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
47 if ((*length >> 24) || *length < 16)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
48 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
49 *length -= 16;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
50 if (get_be32(pb))
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
51 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
52 if (get_byte(pb) != 0xe1)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
53 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
54 if (get_byte(pb) != 0xe2)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
55 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
56 return 1;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
57 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
58
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
59 /**
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
60 * \brief check if file starts with a PKT_MAP header
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
61 */
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
62 static int gxf_probe(AVProbeData *p) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
63 static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
64 static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
65 if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
66 !memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
67 return AVPROBE_SCORE_MAX;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
68 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
69 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
70
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
71 /**
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
72 * \brief gets the stream index for the track with the specified id, creates new
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
73 * stream if not found
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
74 * \param stream id of stream to find / add
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
75 * \param format stream format identifier
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
76 */
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
77 static int get_sindex(AVFormatContext *s, int id, int format) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
78 int i;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
79 AVStream *st = NULL;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
80 for (i = 0; i < s->nb_streams; i++) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
81 if (s->streams[i]->id == id)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
82 return i;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
83 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
84 st = av_new_stream(s, id);
3400
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
85 if (!st)
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
86 return AVERROR(ENOMEM);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
87 switch (format) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
88 case 3:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
89 case 4:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
90 st->codec->codec_type = CODEC_TYPE_VIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
91 st->codec->codec_id = CODEC_ID_MJPEG;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
92 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
93 case 13:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
94 case 15:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
95 st->codec->codec_type = CODEC_TYPE_VIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
96 st->codec->codec_id = CODEC_ID_DVVIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
97 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
98 case 14:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
99 case 16:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
100 st->codec->codec_type = CODEC_TYPE_VIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
101 st->codec->codec_id = CODEC_ID_DVVIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
102 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
103 case 11:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
104 case 12:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
105 case 20:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
106 st->codec->codec_type = CODEC_TYPE_VIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
107 st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
2023
a3e79d6e4e3c add an enum for need_parsing
aurel
parents: 2001
diff changeset
108 st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
109 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
110 case 22:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
111 case 23:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
112 st->codec->codec_type = CODEC_TYPE_VIDEO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
113 st->codec->codec_id = CODEC_ID_MPEG1VIDEO;
2023
a3e79d6e4e3c add an enum for need_parsing
aurel
parents: 2001
diff changeset
114 st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
115 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
116 case 9:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
117 st->codec->codec_type = CODEC_TYPE_AUDIO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
118 st->codec->codec_id = CODEC_ID_PCM_S24LE;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
119 st->codec->channels = 1;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
120 st->codec->sample_rate = 48000;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
121 st->codec->bit_rate = 3 * 1 * 48000 * 8;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
122 st->codec->block_align = 3 * 1;
3908
1d3d17de20ba Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 3424
diff changeset
123 st->codec->bits_per_coded_sample = 24;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
124 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
125 case 10:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
126 st->codec->codec_type = CODEC_TYPE_AUDIO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
127 st->codec->codec_id = CODEC_ID_PCM_S16LE;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
128 st->codec->channels = 1;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
129 st->codec->sample_rate = 48000;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
130 st->codec->bit_rate = 2 * 1 * 48000 * 8;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
131 st->codec->block_align = 2 * 1;
3908
1d3d17de20ba Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 3424
diff changeset
132 st->codec->bits_per_coded_sample = 16;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
133 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
134 case 17:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
135 st->codec->codec_type = CODEC_TYPE_AUDIO;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
136 st->codec->codec_id = CODEC_ID_AC3;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
137 st->codec->channels = 2;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
138 st->codec->sample_rate = 48000;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
139 break;
1539
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
140 // timecode tracks:
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
141 case 7:
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
142 case 8:
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
143 case 24:
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
144 st->codec->codec_type = CODEC_TYPE_DATA;
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
145 st->codec->codec_id = CODEC_ID_NONE;
bc94f4215dd0 Set CODEC_TYPE_DATA for timecode tracks.
reimar
parents: 1538
diff changeset
146 break;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
147 default:
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
148 st->codec->codec_type = CODEC_TYPE_UNKNOWN;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
149 st->codec->codec_id = CODEC_ID_NONE;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
150 break;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
151 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
152 return s->nb_streams - 1;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
153 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
154
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
155 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
156 * \brief filters out interesting tags from material information.
2560
bc13220fb9cd cosmetics: typo
diego
parents: 2282
diff changeset
157 * \param len length of tag section, will be adjusted to contain remaining bytes
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
158 * \param si struct to store collected information into
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
159 */
4074
58051a1dc7ea Use "struct gxf_stream_info" instead of "st_info_t",
reimar
parents: 3939
diff changeset
160 static void gxf_material_tags(ByteIOContext *pb, int *len, struct gxf_stream_info *si) {
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
161 si->first_field = AV_NOPTS_VALUE;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
162 si->last_field = AV_NOPTS_VALUE;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
163 while (*len >= 2) {
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
164 GXFMatTag tag = get_byte(pb);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
165 int tlen = get_byte(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
166 *len -= 2;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
167 if (tlen > *len)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
168 return;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
169 *len -= tlen;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
170 if (tlen == 4) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
171 uint32_t value = get_be32(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
172 if (tag == MAT_FIRST_FIELD)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
173 si->first_field = value;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
174 else if (tag == MAT_LAST_FIELD)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
175 si->last_field = value;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
176 } else
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
177 url_fskip(pb, tlen);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
178 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
179 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
180
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
181 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
182 * \brief convert fps tag value to AVRational fps
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
183 * \param fps fps value from tag
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
184 * \return fps as AVRational, or 0 / 0 if unknown
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
185 */
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
186 static AVRational fps_tag2avr(int32_t fps) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
187 extern const AVRational ff_frame_rate_tab[];
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
188 if (fps < 1 || fps > 9) fps = 9;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
189 return ff_frame_rate_tab[9 - fps]; // values have opposite order
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
190 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
191
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
192 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
193 * \brief convert UMF attributes flags to AVRational fps
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
194 * \param fps fps value from flags
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
195 * \return fps as AVRational, or 0 / 0 if unknown
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
196 */
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
197 static AVRational fps_umf2avr(uint32_t flags) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
198 static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
199 {25, 1}, {30000, 1001}};
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
200 int idx = av_log2((flags & 0x7c0) >> 6);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
201 return map[idx];
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
202 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
203
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
204 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
205 * \brief filters out interesting tags from track information.
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
206 * \param len length of tag section, will be adjusted to contain remaining bytes
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
207 * \param si struct to store collected information into
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
208 */
4074
58051a1dc7ea Use "struct gxf_stream_info" instead of "st_info_t",
reimar
parents: 3939
diff changeset
209 static void gxf_track_tags(ByteIOContext *pb, int *len, struct gxf_stream_info *si) {
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
210 si->frames_per_second = (AVRational){0, 0};
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
211 si->fields_per_frame = 0;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
212 while (*len >= 2) {
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
213 GXFTrackTag tag = get_byte(pb);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
214 int tlen = get_byte(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
215 *len -= 2;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
216 if (tlen > *len)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
217 return;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
218 *len -= tlen;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
219 if (tlen == 4) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
220 uint32_t value = get_be32(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
221 if (tag == TRACK_FPS)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
222 si->frames_per_second = fps_tag2avr(value);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
223 else if (tag == TRACK_FPF && (value == 1 || value == 2))
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
224 si->fields_per_frame = value;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
225 } else
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
226 url_fskip(pb, tlen);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
227 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
228 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
229
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
230 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
231 * \brief read index from FLT packet into stream 0 av_index
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
232 */
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
233 static void gxf_read_index(AVFormatContext *s, int pkt_len) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
234 ByteIOContext *pb = s->pb;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
235 AVStream *st = s->streams[0];
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
236 uint32_t fields_per_map = get_le32(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
237 uint32_t map_cnt = get_le32(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
238 int i;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
239 pkt_len -= 8;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
240 if (map_cnt > 1000) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
241 av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
242 map_cnt = 1000;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
243 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
244 if (pkt_len < 4 * map_cnt) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
245 av_log(s, AV_LOG_ERROR, "invalid index length\n");
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
246 url_fskip(pb, pkt_len);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
247 return;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
248 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
249 pkt_len -= 4 * map_cnt;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
250 av_add_index_entry(st, 0, 0, 0, 0, 0);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
251 for (i = 0; i < map_cnt; i++)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
252 av_add_index_entry(st, (uint64_t)get_le32(pb) * 1024,
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
253 i * (uint64_t)fields_per_map + 1, 0, 0, 0);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
254 url_fskip(pb, pkt_len);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
255 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
256
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
257 static int gxf_header(AVFormatContext *s, AVFormatParameters *ap) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
258 ByteIOContext *pb = s->pb;
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
259 GXFPktType pkt_type;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
260 int map_len;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
261 int len;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
262 AVRational main_timebase = {0, 0};
4074
58051a1dc7ea Use "struct gxf_stream_info" instead of "st_info_t",
reimar
parents: 3939
diff changeset
263 struct gxf_stream_info si;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
264 int i;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
265 if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
266 av_log(s, AV_LOG_ERROR, "map packet not found\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
267 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
268 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
269 map_len -= 2;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
270 if (get_byte(pb) != 0x0e0 || get_byte(pb) != 0xff) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
271 av_log(s, AV_LOG_ERROR, "unknown version or invalid map preamble\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
272 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
273 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
274 map_len -= 2;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
275 len = get_be16(pb); // length of material data section
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
276 if (len > map_len) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
277 av_log(s, AV_LOG_ERROR, "material data longer than map data\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
278 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
279 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
280 map_len -= len;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
281 gxf_material_tags(pb, &len, &si);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
282 url_fskip(pb, len);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
283 map_len -= 2;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
284 len = get_be16(pb); // length of track description
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
285 if (len > map_len) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
286 av_log(s, AV_LOG_ERROR, "track description longer than map data\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
287 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
288 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
289 map_len -= len;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
290 while (len > 0) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
291 int track_type, track_id, track_len;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
292 AVStream *st;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
293 int idx;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
294 len -= 4;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
295 track_type = get_byte(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
296 track_id = get_byte(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
297 track_len = get_be16(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
298 len -= track_len;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
299 gxf_track_tags(pb, &track_len, &si);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
300 url_fskip(pb, track_len);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
301 if (!(track_type & 0x80)) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
302 av_log(s, AV_LOG_ERROR, "invalid track type %x\n", track_type);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
303 continue;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
304 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
305 track_type &= 0x7f;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
306 if ((track_id & 0xc0) != 0xc0) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
307 av_log(s, AV_LOG_ERROR, "invalid track id %x\n", track_id);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
308 continue;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
309 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
310 track_id &= 0x3f;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
311 idx = get_sindex(s, track_id, track_type);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
312 if (idx < 0) continue;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
313 st = s->streams[idx];
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
314 if (!main_timebase.num || !main_timebase.den) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
315 main_timebase.num = si.frames_per_second.den;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
316 main_timebase.den = si.frames_per_second.num * si.fields_per_frame;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
317 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
318 st->start_time = si.first_field;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
319 if (si.first_field != AV_NOPTS_VALUE && si.last_field != AV_NOPTS_VALUE)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
320 st->duration = si.last_field - si.first_field;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
321 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
322 if (len < 0)
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
323 av_log(s, AV_LOG_ERROR, "invalid track description length specified\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
324 if (map_len)
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
325 url_fskip(pb, map_len);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
326 if (!parse_packet_header(pb, &pkt_type, &len)) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
327 av_log(s, AV_LOG_ERROR, "sync lost in header\n");
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
328 return -1;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
329 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
330 if (pkt_type == PKT_FLT) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
331 gxf_read_index(s, len);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
332 if (!parse_packet_header(pb, &pkt_type, &len)) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
333 av_log(s, AV_LOG_ERROR, "sync lost in header\n");
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
334 return -1;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
335 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
336 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
337 if (pkt_type == PKT_UMF) {
1763
e77907af9057 10l, forgot to skip payload description in UMF packet parsing
reimar
parents: 1539
diff changeset
338 if (len >= 0x39) {
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
339 AVRational fps;
1763
e77907af9057 10l, forgot to skip payload description in UMF packet parsing
reimar
parents: 1539
diff changeset
340 len -= 0x39;
e77907af9057 10l, forgot to skip payload description in UMF packet parsing
reimar
parents: 1539
diff changeset
341 url_fskip(pb, 5); // preamble
e77907af9057 10l, forgot to skip payload description in UMF packet parsing
reimar
parents: 1539
diff changeset
342 url_fskip(pb, 0x30); // payload description
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
343 fps = fps_umf2avr(get_le32(pb));
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
344 if (!main_timebase.num || !main_timebase.den) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
345 // this may not always be correct, but simply the best we can get
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
346 main_timebase.num = fps.den;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
347 main_timebase.den = fps.num;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
348 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
349 } else
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
350 av_log(s, AV_LOG_INFO, "UMF packet too short\n");
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
351 } else
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
352 av_log(s, AV_LOG_INFO, "UMF packet missing\n");
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
353 url_fskip(pb, len);
1767
f1186797fbf5 Use av_set_pts_info and set some arbitrary timebase fallback
reimar
parents: 1765
diff changeset
354 if (!main_timebase.num || !main_timebase.den)
f1186797fbf5 Use av_set_pts_info and set some arbitrary timebase fallback
reimar
parents: 1765
diff changeset
355 main_timebase = (AVRational){1, 50}; // set some arbitrary fallback
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
356 for (i = 0; i < s->nb_streams; i++) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
357 AVStream *st = s->streams[i];
1767
f1186797fbf5 Use av_set_pts_info and set some arbitrary timebase fallback
reimar
parents: 1765
diff changeset
358 av_set_pts_info(st, 32, main_timebase.num, main_timebase.den);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
359 }
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
360 return 0;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
361 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
362
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
363 #define READ_ONE() \
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
364 { \
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
365 if (!max_interval-- || url_feof(pb)) \
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
366 goto out; \
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
367 tmp = tmp << 8 | get_byte(pb); \
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
368 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
369
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
370 /**
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
371 * \brief resync the stream on the next media packet with specified properties
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
372 * \param max_interval how many bytes to search for matching packet at most
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
373 * \param track track id the media packet must belong to, -1 for any
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
374 * \param timestamp minimum timestamp (== field number) the packet must have, -1 for any
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
375 * \return timestamp of packet found
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
376 */
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
377 static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
378 uint32_t tmp;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
379 uint64_t last_pos;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
380 uint64_t last_found_pos = 0;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
381 int cur_track;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
382 int64_t cur_timestamp = AV_NOPTS_VALUE;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
383 int len;
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
384 ByteIOContext *pb = s->pb;
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
385 GXFPktType type;
1221
ad456312dd5e Minor resync optimization
reimar
parents: 1219
diff changeset
386 tmp = get_be32(pb);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
387 start:
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
388 while (tmp)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
389 READ_ONE();
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
390 READ_ONE();
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
391 if (tmp != 1)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
392 goto start;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
393 last_pos = url_ftell(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
394 url_fseek(pb, -5, SEEK_CUR);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
395 if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
396 url_fseek(pb, last_pos, SEEK_SET);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
397 goto start;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
398 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
399 get_byte(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
400 cur_track = get_byte(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
401 cur_timestamp = get_be32(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
402 last_found_pos = url_ftell(pb) - 16 - 6;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
403 if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
404 url_fseek(pb, last_pos, SEEK_SET);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
405 goto start;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
406 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
407 out:
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
408 if (last_found_pos)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
409 url_fseek(pb, last_found_pos, SEEK_SET);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
410 return cur_timestamp;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
411 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
412
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
413 static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
414 ByteIOContext *pb = s->pb;
4098
10d52cda08dd Avoid _t in gxf enum type names
reimar
parents: 4074
diff changeset
415 GXFPktType pkt_type;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
416 int pkt_len;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
417 while (!url_feof(pb)) {
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
418 AVStream *st;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
419 int track_type, track_id, ret;
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
420 int field_nr, field_info, skip = 0;
3400
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
421 int stream_index;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
422 if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
423 if (!url_feof(pb))
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
424 av_log(s, AV_LOG_ERROR, "sync lost\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
425 return -1;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
426 }
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
427 if (pkt_type == PKT_FLT) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
428 gxf_read_index(s, pkt_len);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
429 continue;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
430 }
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
431 if (pkt_type != PKT_MEDIA) {
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
432 url_fskip(pb, pkt_len);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
433 continue;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
434 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
435 if (pkt_len < 16) {
3939
20da3b0e6adf cosmetics, remove GXF: in log messages since it is present in context
bcoudurier
parents: 3938
diff changeset
436 av_log(s, AV_LOG_ERROR, "invalid media packet length\n");
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
437 continue;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
438 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
439 pkt_len -= 16;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
440 track_type = get_byte(pb);
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
441 track_id = get_byte(pb);
3400
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
442 stream_index = get_sindex(s, track_id, track_type);
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
443 if (stream_index < 0)
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
444 return stream_index;
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
445 st = s->streams[stream_index];
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
446 field_nr = get_be32(pb);
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
447 field_info = get_be32(pb);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
448 get_be32(pb); // "timeline" field number
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
449 get_byte(pb); // flags
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
450 get_byte(pb); // reserved
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
451 if (st->codec->codec_id == CODEC_ID_PCM_S24LE ||
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
452 st->codec->codec_id == CODEC_ID_PCM_S16LE) {
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
453 int first = field_info >> 16;
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
454 int last = field_info & 0xffff; // last is exclusive
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
455 int bps = av_get_bits_per_sample(st->codec->codec_id)>>3;
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
456 if (first <= last && last*bps <= pkt_len) {
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
457 url_fskip(pb, first*bps);
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
458 skip = pkt_len - last*bps;
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
459 pkt_len = (last-first)*bps;
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
460 } else
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
461 av_log(s, AV_LOG_ERROR, "invalid first and last sample values\n");
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
462 }
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
463 ret = av_get_packet(pb, pkt, pkt_len);
3938
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
464 if (skip)
aaae317c3d54 skip invalid audio samples in gxf packets
bcoudurier
parents: 3908
diff changeset
465 url_fskip(pb, skip);
3400
75d4db7ae5c9 Check for av_new_stream failure, fixes CID76 RUN2
reimar
parents: 3286
diff changeset
466 pkt->stream_index = stream_index;
1243
088e77e1d06f both timestamps are dts, (checked trailer.gxf, spec is unclear)
michael
parents: 1222
diff changeset
467 pkt->dts = field_nr;
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
468 return ret;
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
469 }
2274
b21c2af60bc9 Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents: 2023
diff changeset
470 return AVERROR(EIO);
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
471 }
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
472
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
473 static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
474 uint64_t pos;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
475 uint64_t maxlen = 100 * 1024 * 1024;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
476 AVStream *st = s->streams[0];
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
477 int64_t start_time = s->streams[stream_index]->start_time;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
478 int64_t found;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
479 int idx;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
480 if (timestamp < start_time) timestamp = start_time;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
481 idx = av_index_search_timestamp(st, timestamp - start_time,
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
482 AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
483 if (idx < 0)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
484 return -1;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
485 pos = st->index_entries[idx].pos;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
486 if (idx < st->nb_index_entries - 2)
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
487 maxlen = st->index_entries[idx + 2].pos - pos;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
488 maxlen = FFMAX(maxlen, 200 * 1024);
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
489 url_fseek(s->pb, pos, SEEK_SET);
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
490 found = gxf_resync_media(s, maxlen, -1, timestamp);
1379
4146500158b5 Rename ABS macro to FFABS.
diego
parents: 1358
diff changeset
491 if (FFABS(found - timestamp) > 4)
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
492 return -1;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
493 return 0;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
494 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
495
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
496 static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
497 int64_t *pos, int64_t pos_limit) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2560
diff changeset
498 ByteIOContext *pb = s->pb;
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
499 int64_t res;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
500 url_fseek(pb, *pos, SEEK_SET);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
501 res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
502 *pos = url_ftell(pb);
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
503 return res;
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
504 }
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
505
1169
d18cc9a1fd02 allow individual selection of muxers and demuxers
mru
parents: 1167
diff changeset
506 AVInputFormat gxf_demuxer = {
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
507 "gxf",
3424
7a0230981402 Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents: 3400
diff changeset
508 NULL_IF_CONFIG_SMALL("GXF format"),
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
509 0,
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
510 gxf_probe,
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
511 gxf_header,
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
512 gxf_packet,
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
513 NULL,
1214
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
514 gxf_seek,
4dbf4b5e675d Support for seeking, both with and without index and correct timestamps
reimar
parents: 1207
diff changeset
515 gxf_read_timestamp,
1145
95054d76b7e6 add GXF demuxer
reimar
parents:
diff changeset
516 };