Mercurial > libavformat.hg
annotate flvdec.c @ 2400:fcaecfb05781 libavformat
When looking for the last packet in each
stream, so as to calculate the duration, don't stop
as soon as all streams have seen at least one packet.
Otherwise the duration will be shorter than it
should be. We must keep reading to the end-of-file.
patch by neilb suse de
author | michael |
---|---|
date | Sat, 18 Aug 2007 00:52:05 +0000 |
parents | b21c2af60bc9 |
children | 74c1aa100084 |
rev | line source |
---|---|
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
1 /* |
1415
3b00fb8ef8e4
replace coder/decoder file description in libavformat by muxer/demuxer
aurel
parents:
1414
diff
changeset
|
2 * FLV demuxer |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
3 * Copyright (c) 2003 The FFmpeg Project. |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
4 * |
2216 | 5 * This demuxer will generate a 1 byte extradata for VP6F content. |
6 * It is composed of: | |
7 * - upper 4bits: difference between encoded width and visible width | |
8 * - lower 4bits: difference between encoded height and visible height | |
9 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1318
diff
changeset
|
10 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1318
diff
changeset
|
11 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1318
diff
changeset
|
12 * FFmpeg is free software; you can redistribute it and/or |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
13 * modify it under the terms of the GNU Lesser General Public |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
14 * 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:
1318
diff
changeset
|
15 * version 2.1 of the License, or (at your option) any later version. |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
16 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1318
diff
changeset
|
17 * FFmpeg is distributed in the hope that it will be useful, |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
20 * Lesser General Public License for more details. |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
21 * |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
22 * 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:
1318
diff
changeset
|
23 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
25 */ |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
26 #include "avformat.h" |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
27 #include "flv.h" |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
28 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
29 static int flv_probe(AVProbeData *p) |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
30 { |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
31 const uint8_t *d; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
32 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
33 d = p->buf; |
1718 | 34 if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5]==0) { |
35 return AVPROBE_SCORE_MAX; | |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
36 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
37 return 0; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
38 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
39 |
1568 | 40 static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_codecid) { |
41 AVCodecContext *acodec = astream->codec; | |
42 switch(flv_codecid) { | |
43 //no distinction between S16 and S8 PCM codec flags | |
44 case FLV_CODECID_PCM_BE: | |
45 acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 : CODEC_ID_PCM_S16BE; break; | |
46 case FLV_CODECID_PCM_LE: | |
47 acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 : CODEC_ID_PCM_S16LE; break; | |
48 case FLV_CODECID_ADPCM: acodec->codec_id = CODEC_ID_ADPCM_SWF; break; | |
2023 | 49 case FLV_CODECID_MP3 : acodec->codec_id = CODEC_ID_MP3 ; astream->need_parsing = AVSTREAM_PARSE_FULL; break; |
1568 | 50 case FLV_CODECID_NELLYMOSER_8HZ_MONO: |
51 acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate | |
52 case FLV_CODECID_NELLYMOSER: | |
53 default: | |
54 av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET); | |
55 acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; | |
56 } | |
57 } | |
58 | |
59 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid) { | |
60 AVCodecContext *vcodec = vstream->codec; | |
61 switch(flv_codecid) { | |
62 case FLV_CODECID_H263 : vcodec->codec_id = CODEC_ID_FLV1 ; break; | |
63 case FLV_CODECID_SCREEN: vcodec->codec_id = CODEC_ID_FLASHSV; break; | |
64 case FLV_CODECID_VP6 : vcodec->codec_id = CODEC_ID_VP6F ; | |
65 if(vcodec->extradata_size != 1) { | |
66 vcodec->extradata_size = 1; | |
67 vcodec->extradata = av_malloc(1); | |
68 } | |
69 vcodec->extradata[0] = get_byte(&s->pb); | |
70 return 1; // 1 byte body size adjustment for flv_read_packet() | |
71 default: | |
72 av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); | |
73 vcodec->codec_tag = flv_codecid; | |
74 } | |
75 | |
76 return 0; | |
77 } | |
78 | |
1560
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
79 static int amf_get_string(ByteIOContext *ioc, char *buffer, int buffsize) { |
1561 | 80 int length = get_be16(ioc); |
1560
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
81 if(length >= buffsize) { |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
82 url_fskip(ioc, length); |
1561 | 83 return -1; |
1560
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
84 } |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
85 |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
86 get_buffer(ioc, buffer, length); |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
87 |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
88 buffer[length] = '\0'; |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
89 |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
90 return length; |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
91 } |
f59b66f9d679
amf_get_string() by Allan Hsu allan aat counterpop doot net
michael
parents:
1559
diff
changeset
|
92 |
1568 | 93 static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, unsigned int max_pos, int depth) { |
94 AVCodecContext *acodec, *vcodec; | |
95 ByteIOContext *ioc; | |
96 AMFDataType amf_type; | |
97 char str_val[256]; | |
98 double num_val; | |
99 | |
100 num_val = 0; | |
101 ioc = &s->pb; | |
102 | |
103 amf_type = get_byte(ioc); | |
104 | |
105 switch(amf_type) { | |
106 case AMF_DATA_TYPE_NUMBER: | |
107 num_val = av_int2dbl(get_be64(ioc)); break; | |
108 case AMF_DATA_TYPE_BOOL: | |
109 num_val = get_byte(ioc); break; | |
110 case AMF_DATA_TYPE_STRING: | |
111 if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0) | |
112 return -1; | |
113 break; | |
114 case AMF_DATA_TYPE_OBJECT: { | |
115 unsigned int keylen; | |
116 | |
117 while(url_ftell(ioc) < max_pos - 2 && (keylen = get_be16(ioc))) { | |
118 url_fskip(ioc, keylen); //skip key string | |
119 if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0) | |
120 return -1; //if we couldn't skip, bomb out. | |
121 } | |
122 if(get_byte(ioc) != AMF_END_OF_OBJECT) | |
123 return -1; | |
124 } | |
125 break; | |
126 case AMF_DATA_TYPE_NULL: | |
127 case AMF_DATA_TYPE_UNDEFINED: | |
128 case AMF_DATA_TYPE_UNSUPPORTED: | |
129 break; //these take up no additional space | |
130 case AMF_DATA_TYPE_MIXEDARRAY: | |
131 url_fskip(ioc, 4); //skip 32-bit max array index | |
132 while(url_ftell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { | |
133 //this is the only case in which we would want a nested parse to not skip over the object | |
134 if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0) | |
135 return -1; | |
136 } | |
137 if(get_byte(ioc) != AMF_END_OF_OBJECT) | |
138 return -1; | |
139 break; | |
140 case AMF_DATA_TYPE_ARRAY: { | |
141 unsigned int arraylen, i; | |
142 | |
143 arraylen = get_be32(ioc); | |
144 for(i = 0; i < arraylen && url_ftell(ioc) < max_pos - 1; i++) { | |
145 if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0) | |
146 return -1; //if we couldn't skip, bomb out. | |
147 } | |
148 } | |
149 break; | |
150 case AMF_DATA_TYPE_DATE: | |
151 url_fskip(ioc, 8 + 2); //timestamp (double) and UTC offset (int16) | |
152 break; | |
153 default: //unsupported type, we couldn't skip | |
154 return -1; | |
155 } | |
156 | |
157 if(depth == 1 && key) { //only look for metadata values when we are not nested and key != NULL | |
158 acodec = astream ? astream->codec : NULL; | |
159 vcodec = vstream ? vstream->codec : NULL; | |
160 | |
161 if(amf_type == AMF_DATA_TYPE_BOOL) { | |
162 if(!strcmp(key, "stereo") && acodec) acodec->channels = num_val > 0 ? 2 : 1; | |
163 } else if(amf_type == AMF_DATA_TYPE_NUMBER) { | |
164 if(!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE; | |
1719
f813f8755dd1
flv follows in movs footsteps and has random trash in the width/height fields
michael
parents:
1718
diff
changeset
|
165 // else if(!strcmp(key, "width") && vcodec && num_val > 0) vcodec->width = num_val; |
f813f8755dd1
flv follows in movs footsteps and has random trash in the width/height fields
michael
parents:
1718
diff
changeset
|
166 // else if(!strcmp(key, "height") && vcodec && num_val > 0) vcodec->height = num_val; |
1568 | 167 else if(!strcmp(key, "audiocodecid") && acodec) flv_set_audio_codec(s, astream, (int)num_val << FLV_AUDIO_CODECID_OFFSET); |
168 else if(!strcmp(key, "videocodecid") && vcodec) flv_set_video_codec(s, vstream, (int)num_val); | |
169 else if(!strcmp(key, "audiosamplesize") && acodec && num_val >= 0) { | |
170 acodec->bits_per_sample = num_val; | |
171 //we may have to rewrite a previously read codecid because FLV only marks PCM endianness. | |
172 if(num_val == 8 && (acodec->codec_id == CODEC_ID_PCM_S16BE || acodec->codec_id == CODEC_ID_PCM_S16LE)) | |
173 acodec->codec_id = CODEC_ID_PCM_S8; | |
174 } | |
175 else if(!strcmp(key, "audiosamplerate") && acodec && num_val >= 0) { | |
176 //some tools, like FLVTool2, write consistently approximate metadata sample rates | |
177 switch((int)num_val) { | |
178 case 44000: acodec->sample_rate = 44100 ; break; | |
179 case 22000: acodec->sample_rate = 22050 ; break; | |
180 case 11000: acodec->sample_rate = 11025 ; break; | |
181 case 5000 : acodec->sample_rate = 5512 ; break; | |
182 default : acodec->sample_rate = num_val; | |
183 } | |
184 } | |
185 } | |
186 } | |
187 | |
188 return 0; | |
189 } | |
190 | |
191 static int flv_read_metabody(AVFormatContext *s, unsigned int next_pos) { | |
192 AMFDataType type; | |
193 AVStream *stream, *astream, *vstream; | |
194 ByteIOContext *ioc; | |
195 int i, keylen; | |
196 char buffer[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want. | |
197 | |
198 astream = NULL; | |
199 vstream = NULL; | |
200 keylen = 0; | |
201 ioc = &s->pb; | |
202 | |
203 //first object needs to be "onMetaData" string | |
204 type = get_byte(ioc); | |
205 if(type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0 || strcmp(buffer, "onMetaData")) | |
206 return -1; | |
207 | |
208 //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called. | |
209 for(i = 0; i < s->nb_streams; i++) { | |
210 stream = s->streams[i]; | |
211 if (stream->codec->codec_type == CODEC_TYPE_AUDIO) astream = stream; | |
212 else if(stream->codec->codec_type == CODEC_TYPE_VIDEO) vstream = stream; | |
213 } | |
214 | |
215 //parse the second object (we want a mixed array) | |
216 if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0) | |
217 return -1; | |
218 | |
219 return 0; | |
220 } | |
221 | |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
222 static int flv_read_header(AVFormatContext *s, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
223 AVFormatParameters *ap) |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
224 { |
1563
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
225 int offset, flags; |
1559
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
226 AVStream *st; |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
227 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
228 url_fskip(&s->pb, 4); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
229 flags = get_byte(&s->pb); |
1886 | 230 /* old flvtool cleared this field */ |
231 /* FIXME: better fix needed */ | |
232 if (!flags) { | |
233 flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO; | |
234 av_log(s, AV_LOG_WARNING, "Broken FLV file, which says no streams present, this might fail\n"); | |
235 } | |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
236 |
1559
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
237 if(flags & FLV_HEADER_FLAG_HASVIDEO){ |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
238 st = av_new_stream(s, 0); |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
239 if (!st) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2216
diff
changeset
|
240 return AVERROR(ENOMEM); |
1559
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
241 st->codec->codec_type = CODEC_TYPE_VIDEO; |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
242 av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */ |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
243 } |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
244 if(flags & FLV_HEADER_FLAG_HASAUDIO){ |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
245 st = av_new_stream(s, 1); |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
246 if (!st) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2216
diff
changeset
|
247 return AVERROR(ENOMEM); |
1559
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
248 st->codec->codec_type = CODEC_TYPE_AUDIO; |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
249 av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */ |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
250 } |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
251 |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
252 offset = get_be32(&s->pb); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
253 url_fseek(&s->pb, offset, SEEK_SET); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
254 |
1318 | 255 s->start_time = 0; |
256 | |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
257 return 0; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
258 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
259 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
260 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
261 { |
1318 | 262 int ret, i, type, size, pts, flags, is_audio, next, pos; |
679 | 263 AVStream *st = NULL; |
885 | 264 |
445 | 265 for(;;){ |
1318 | 266 pos = url_ftell(&s->pb); |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
267 url_fskip(&s->pb, 4); /* size of previous packet */ |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
268 type = get_byte(&s->pb); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
269 size = get_be24(&s->pb); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
270 pts = get_be24(&s->pb); |
376 | 271 // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts); |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
272 if (url_feof(&s->pb)) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
273 return AVERROR(EIO); |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
274 url_fskip(&s->pb, 4); /* reserved */ |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
275 flags = 0; |
885 | 276 |
445 | 277 if(size == 0) |
278 continue; | |
885 | 279 |
821 | 280 next= size + url_ftell(&s->pb); |
281 | |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
282 if (type == FLV_TAG_TYPE_AUDIO) { |
445 | 283 is_audio=1; |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
284 flags = get_byte(&s->pb); |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
285 } else if (type == FLV_TAG_TYPE_VIDEO) { |
445 | 286 is_audio=0; |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
287 flags = get_byte(&s->pb); |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
288 } else { |
1568 | 289 if (type == FLV_TAG_TYPE_META && size > 13+1+4) |
290 flv_read_metabody(s, next); | |
291 else /* skip packet */ | |
292 av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); | |
821 | 293 url_fseek(&s->pb, next, SEEK_SET); |
445 | 294 continue; |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
295 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
296 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
297 /* now find stream */ |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
298 for(i=0;i<s->nb_streams;i++) { |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
299 st = s->streams[i]; |
445 | 300 if (st->id == is_audio) |
301 break; | |
302 } | |
303 if(i == s->nb_streams){ | |
1559
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
304 av_log(NULL, AV_LOG_ERROR, "invalid stream\n"); |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
305 url_fseek(&s->pb, next, SEEK_SET); |
515e80ef01e6
get rid of AVFMTCTX_NOHEADER, create streams in read_header()
michael
parents:
1553
diff
changeset
|
306 continue; |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
307 } |
708 | 308 // av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard); |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
309 if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio)) |
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
310 ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) |
708 | 311 || st->discard >= AVDISCARD_ALL |
312 ){ | |
821 | 313 url_fseek(&s->pb, next, SEEK_SET); |
652 | 314 continue; |
315 } | |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
316 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) |
1318 | 317 av_add_index_entry(st, pos, pts, size, 0, AVINDEX_KEYFRAME); |
445 | 318 break; |
319 } | |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
320 |
1563
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
321 // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
322 if(!url_is_streamed(&s->pb) && s->duration==AV_NOPTS_VALUE){ |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
323 int size; |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
324 const int pos= url_ftell(&s->pb); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
325 const int fsize= url_fsize(&s->pb); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
326 url_fseek(&s->pb, fsize-4, SEEK_SET); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
327 size= get_be32(&s->pb); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
328 url_fseek(&s->pb, fsize-3-size, SEEK_SET); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
329 if(size == get_be24(&s->pb) + 11){ |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
330 s->duration= get_be24(&s->pb) * (int64_t)AV_TIME_BASE / 1000; |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
331 } |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
332 url_fseek(&s->pb, pos, SEEK_SET); |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
333 } |
bf3589ba8d7e
move duration finding code into read_packet() so it can be skiped if duration has already been set
michael
parents:
1562
diff
changeset
|
334 |
445 | 335 if(is_audio){ |
1568 | 336 if(!st->codec->sample_rate || !st->codec->bits_per_sample || (!st->codec->codec_id && !st->codec->codec_tag)) { |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
337 st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1; |
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
338 if((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_NELLYMOSER_8HZ_MONO) |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
339 st->codec->sample_rate= 8000; |
445 | 340 else |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
341 st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3); |
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
342 st->codec->bits_per_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; |
1568 | 343 flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK); |
445 | 344 } |
345 }else{ | |
1568 | 346 size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK); |
378 | 347 } |
348 | |
821 | 349 ret= av_get_packet(&s->pb, pkt, size - 1); |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
350 if (ret <= 0) { |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
351 return AVERROR(EIO); |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
352 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
353 /* note: we need to modify the packet size here to handle the last |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
354 packet */ |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
355 pkt->size = ret; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
356 pkt->pts = pts; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
357 pkt->stream_index = st->index; |
885 | 358 |
1553
504ceaa50e31
Defines various common FLV format values between the FLV muxer and demuxer
aurel
parents:
1415
diff
changeset
|
359 if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) |
887 | 360 pkt->flags |= PKT_FLAG_KEY; |
885 | 361 |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
362 return ret; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
363 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
364 |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
365 static int flv_read_close(AVFormatContext *s) |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
366 { |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
367 return 0; |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
368 } |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
369 |
1318 | 370 static int flv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
371 { | |
372 AVStream *st = s->streams[stream_index]; | |
373 int index = av_index_search_timestamp(st, timestamp, flags); | |
374 if (index < 0) | |
375 return -1; | |
376 url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET); | |
377 | |
378 return 0; | |
379 } | |
380 | |
1167 | 381 AVInputFormat flv_demuxer = { |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
382 "flv", |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
383 "flv format", |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
384 0, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
385 flv_probe, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
386 flv_read_header, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
387 flv_read_packet, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
388 flv_read_close, |
1318 | 389 flv_read_seek, |
164
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
390 .extensions = "flv", |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
391 .value = CODEC_ID_FLV1, |
99fbacf0f764
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
michaelni
parents:
diff
changeset
|
392 }; |