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,