Mercurial > libavformat.hg
comparison flvdec.c @ 2558:74c1aa100084 libavformat
Add support for VP6A in flv.
Those files really contain 2 standard VP6 video streams:
- the "normal" video stream
- the alpha plan video stream (which is a standard
YV12 video with it's U an V plans all set to 0)
closes issue166
author | aurel |
---|---|
date | Tue, 18 Sep 2007 15:36:29 +0000 |
parents | b21c2af60bc9 |
children | 41fefa61d999 |
comparison
equal
deleted
inserted
replaced
2557:0c4febec2258 | 2558:74c1aa100084 |
---|---|
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
25 */ | 25 */ |
26 #include "avformat.h" | 26 #include "avformat.h" |
27 #include "flv.h" | 27 #include "flv.h" |
28 | 28 |
29 typedef struct { | |
30 AVStream *alpha_stream; | |
31 int pts; | |
32 int flags; | |
33 int alpha_size; | |
34 } FLVContext; | |
35 | |
29 static int flv_probe(AVProbeData *p) | 36 static int flv_probe(AVProbeData *p) |
30 { | 37 { |
31 const uint8_t *d; | 38 const uint8_t *d; |
32 | 39 |
33 d = p->buf; | 40 d = p->buf; |
55 acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; | 62 acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; |
56 } | 63 } |
57 } | 64 } |
58 | 65 |
59 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid) { | 66 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid) { |
67 FLVContext *flv = s->priv_data; | |
60 AVCodecContext *vcodec = vstream->codec; | 68 AVCodecContext *vcodec = vstream->codec; |
61 switch(flv_codecid) { | 69 switch(flv_codecid) { |
62 case FLV_CODECID_H263 : vcodec->codec_id = CODEC_ID_FLV1 ; break; | 70 case FLV_CODECID_H263 : vcodec->codec_id = CODEC_ID_FLV1 ; break; |
63 case FLV_CODECID_SCREEN: vcodec->codec_id = CODEC_ID_FLASHSV; break; | 71 case FLV_CODECID_SCREEN: vcodec->codec_id = CODEC_ID_FLASHSV; break; |
72 case FLV_CODECID_VP6A : | |
73 if (!flv->alpha_stream) { | |
74 AVCodecContext *alpha_codec; | |
75 flv->alpha_stream = av_new_stream(s, 2); | |
76 if (flv->alpha_stream) { | |
77 av_set_pts_info(flv->alpha_stream, 24, 1, 1000); | |
78 alpha_codec = flv->alpha_stream->codec; | |
79 alpha_codec->codec_type = CODEC_TYPE_VIDEO; | |
80 alpha_codec->codec_id = CODEC_ID_VP6F; | |
81 alpha_codec->extradata_size = 1; | |
82 alpha_codec->extradata = av_malloc(1); | |
83 } | |
84 } | |
64 case FLV_CODECID_VP6 : vcodec->codec_id = CODEC_ID_VP6F ; | 85 case FLV_CODECID_VP6 : vcodec->codec_id = CODEC_ID_VP6F ; |
65 if(vcodec->extradata_size != 1) { | 86 if(vcodec->extradata_size != 1) { |
66 vcodec->extradata_size = 1; | 87 vcodec->extradata_size = 1; |
67 vcodec->extradata = av_malloc(1); | 88 vcodec->extradata = av_malloc(1); |
68 } | 89 } |
69 vcodec->extradata[0] = get_byte(&s->pb); | 90 vcodec->extradata[0] = get_byte(&s->pb); |
91 if (flv->alpha_stream) | |
92 flv->alpha_stream->codec->extradata[0] = vcodec->extradata[0]; | |
70 return 1; // 1 byte body size adjustment for flv_read_packet() | 93 return 1; // 1 byte body size adjustment for flv_read_packet() |
71 default: | 94 default: |
72 av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); | 95 av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); |
73 vcodec->codec_tag = flv_codecid; | 96 vcodec->codec_tag = flv_codecid; |
74 } | 97 } |
257 return 0; | 280 return 0; |
258 } | 281 } |
259 | 282 |
260 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) | 283 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
261 { | 284 { |
262 int ret, i, type, size, pts, flags, is_audio, next, pos; | 285 int ret, i, type, size, flags, is_audio, next, pos; |
286 FLVContext *flv = s->priv_data; | |
263 AVStream *st = NULL; | 287 AVStream *st = NULL; |
288 | |
289 if (flv->alpha_stream && flv->alpha_size) { | |
290 is_audio = 0; | |
291 size = flv->alpha_size; | |
292 flv->alpha_size = 0; | |
293 flags = flv->flags; | |
294 st = flv->alpha_stream; | |
295 goto packet; | |
296 } | |
264 | 297 |
265 for(;;){ | 298 for(;;){ |
266 pos = url_ftell(&s->pb); | 299 pos = url_ftell(&s->pb); |
267 url_fskip(&s->pb, 4); /* size of previous packet */ | 300 url_fskip(&s->pb, 4); /* size of previous packet */ |
268 type = get_byte(&s->pb); | 301 type = get_byte(&s->pb); |
269 size = get_be24(&s->pb); | 302 size = get_be24(&s->pb); |
270 pts = get_be24(&s->pb); | 303 flv->pts = get_be24(&s->pb); |
271 // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts); | 304 // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, flv->pts); |
272 if (url_feof(&s->pb)) | 305 if (url_feof(&s->pb)) |
273 return AVERROR(EIO); | 306 return AVERROR(EIO); |
274 url_fskip(&s->pb, 4); /* reserved */ | 307 url_fskip(&s->pb, 4); /* reserved */ |
275 flags = 0; | 308 flags = 0; |
276 | 309 |
312 ){ | 345 ){ |
313 url_fseek(&s->pb, next, SEEK_SET); | 346 url_fseek(&s->pb, next, SEEK_SET); |
314 continue; | 347 continue; |
315 } | 348 } |
316 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) | 349 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) |
317 av_add_index_entry(st, pos, pts, size, 0, AVINDEX_KEYFRAME); | 350 av_add_index_entry(st, pos, flv->pts, size, 0, AVINDEX_KEYFRAME); |
318 break; | 351 break; |
319 } | 352 } |
320 | 353 |
321 // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps | 354 // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps |
322 if(!url_is_streamed(&s->pb) && s->duration==AV_NOPTS_VALUE){ | 355 if(!url_is_streamed(&s->pb) && s->duration==AV_NOPTS_VALUE){ |
344 } | 377 } |
345 }else{ | 378 }else{ |
346 size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK); | 379 size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK); |
347 } | 380 } |
348 | 381 |
382 if ((flags & FLV_VIDEO_CODECID_MASK) == FLV_CODECID_VP6A) { | |
383 int alpha_offset = get_be24(&s->pb); | |
384 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) | |
385 av_add_index_entry(flv->alpha_stream, pos, flv->pts, size, | |
386 0, AVINDEX_KEYFRAME); | |
387 flv->alpha_size = size - 3 - alpha_offset; | |
388 size = alpha_offset + 1; | |
389 flv->flags = flags; | |
390 } | |
391 packet: | |
349 ret= av_get_packet(&s->pb, pkt, size - 1); | 392 ret= av_get_packet(&s->pb, pkt, size - 1); |
350 if (ret <= 0) { | 393 if (ret <= 0) { |
351 return AVERROR(EIO); | 394 return AVERROR(EIO); |
352 } | 395 } |
353 /* note: we need to modify the packet size here to handle the last | 396 /* note: we need to modify the packet size here to handle the last |
354 packet */ | 397 packet */ |
355 pkt->size = ret; | 398 pkt->size = ret; |
356 pkt->pts = pts; | 399 pkt->pts = flv->pts; |
357 pkt->stream_index = st->index; | 400 pkt->stream_index = st->index; |
358 | 401 |
359 if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) | 402 if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) |
360 pkt->flags |= PKT_FLAG_KEY; | 403 pkt->flags |= PKT_FLAG_KEY; |
361 | 404 |
379 } | 422 } |
380 | 423 |
381 AVInputFormat flv_demuxer = { | 424 AVInputFormat flv_demuxer = { |
382 "flv", | 425 "flv", |
383 "flv format", | 426 "flv format", |
384 0, | 427 sizeof(FLVContext), |
385 flv_probe, | 428 flv_probe, |
386 flv_read_header, | 429 flv_read_header, |
387 flv_read_packet, | 430 flv_read_packet, |
388 flv_read_close, | 431 flv_read_close, |
389 flv_read_seek, | 432 flv_read_seek, |