Mercurial > libavformat.hg
comparison rmdec.c @ 2653:67667d13bab5 libavformat
Demux full frames instead of sliced for RealVideo.
Some changes by Roberto Togni and blessed by him on IRC.
author | kostya |
---|---|
date | Sun, 21 Oct 2007 17:17:28 +0000 |
parents | ecd8a9aa182d |
children | 997fb1ac4783 |
comparison
equal
deleted
inserted
replaced
2652:2d28b2a5b2e4 | 2653:67667d13bab5 |
---|---|
348 header_end: | 348 header_end: |
349 rm->nb_packets = get_be32(pb); /* number of packets */ | 349 rm->nb_packets = get_be32(pb); /* number of packets */ |
350 if (!rm->nb_packets && (flags & 4)) | 350 if (!rm->nb_packets && (flags & 4)) |
351 rm->nb_packets = 3600 * 25; | 351 rm->nb_packets = 3600 * 25; |
352 get_be32(pb); /* next data header */ | 352 get_be32(pb); /* next data header */ |
353 rm->curpic_num = -1; | |
353 return 0; | 354 return 0; |
354 | 355 |
355 fail: | 356 fail: |
356 for(i=0;i<s->nb_streams;i++) { | 357 for(i=0;i<s->nb_streams;i++) { |
357 av_free(s->streams[i]); | 358 av_free(s->streams[i]); |
363 { | 364 { |
364 int n, n1; | 365 int n, n1; |
365 | 366 |
366 n = get_be16(pb); | 367 n = get_be16(pb); |
367 (*len)-=2; | 368 (*len)-=2; |
369 n &= 0x7FFF; | |
368 if (n >= 0x4000) { | 370 if (n >= 0x4000) { |
369 return n - 0x4000; | 371 return n - 0x4000; |
370 } else { | 372 } else { |
371 n1 = get_be16(pb); | 373 n1 = get_be16(pb); |
372 (*len)-=2; | 374 (*len)-=2; |
429 *stream_index= i; | 431 *stream_index= i; |
430 | 432 |
431 return len; | 433 return len; |
432 } | 434 } |
433 return -1; | 435 return -1; |
436 } | |
437 | |
438 static int rm_assemble_video_frame(AVFormatContext *s, RMContext *rm, AVPacket *pkt, int len) | |
439 { | |
440 ByteIOContext *pb = &s->pb; | |
441 int hdr, seq, pic_num, len2, pos; | |
442 int type; | |
443 int ssize; | |
444 | |
445 hdr = get_byte(pb); len--; | |
446 type = hdr >> 6; | |
447 switch(type){ | |
448 case 0: // slice | |
449 case 2: // last slice | |
450 seq = get_byte(pb); len--; | |
451 len2 = get_num(pb, &len); | |
452 pos = get_num(pb, &len); | |
453 pic_num = get_byte(pb); len--; | |
454 rm->remaining_len = len; | |
455 break; | |
456 case 1: //whole frame | |
457 seq = get_byte(pb); len--; | |
458 if(av_new_packet(pkt, len + 9) < 0) | |
459 return AVERROR(EIO); | |
460 pkt->data[0] = 0; | |
461 AV_WL32(pkt->data + 1, 1); | |
462 AV_WL32(pkt->data + 5, 0); | |
463 get_buffer(pb, pkt->data + 9, len); | |
464 rm->remaining_len = 0; | |
465 return 0; | |
466 case 3: //frame as a part of packet | |
467 len2 = get_num(pb, &len); | |
468 pos = get_num(pb, &len); | |
469 pic_num = get_byte(pb); len--; | |
470 rm->remaining_len = len - len2; | |
471 if(av_new_packet(pkt, len2 + 9) < 0) | |
472 return AVERROR(EIO); | |
473 pkt->data[0] = 0; | |
474 AV_WL32(pkt->data + 1, 1); | |
475 AV_WL32(pkt->data + 5, 0); | |
476 get_buffer(pb, pkt->data + 9, len2); | |
477 return 0; | |
478 } | |
479 //now we have to deal with single slice | |
480 | |
481 if((seq & 0x7F) == 1 || rm->curpic_num != pic_num){ | |
482 rm->slices = ((hdr & 0x3F) << 1) + 1; | |
483 ssize = len2 + 8*rm->slices + 1; | |
484 rm->videobuf = av_realloc(rm->videobuf, ssize); | |
485 rm->videobufsize = ssize; | |
486 rm->videobufpos = 8*rm->slices + 1; | |
487 rm->cur_slice = 0; | |
488 rm->curpic_num = pic_num; | |
489 } | |
490 if(type == 2){ | |
491 len = FFMIN(len, pos); | |
492 pos = len2 - pos; | |
493 } | |
494 | |
495 if(++rm->cur_slice > rm->cur_slice) | |
496 return 1; | |
497 AV_WL32(rm->videobuf - 7 + 8*rm->cur_slice, 1); | |
498 AV_WL32(rm->videobuf - 3 + 8*rm->cur_slice, rm->videobufpos - 8*rm->slices - 1); | |
499 if(rm->videobufpos + len > rm->videobufsize) | |
500 return 1; | |
501 if (get_buffer(pb, rm->videobuf + rm->videobufpos, len) != len) | |
502 return AVERROR(EIO); | |
503 rm->videobufpos += len, | |
504 rm->remaining_len-= len; | |
505 | |
506 if(type == 2 || (rm->videobufpos) == rm->videobufsize){ | |
507 //adjust slice headers | |
508 memmove(rm->videobuf + 1 + 8*rm->cur_slice, rm->videobuf + 1 + 8*rm->slices, rm->videobufsize - 1 - 8*rm->slices); | |
509 ssize = rm->videobufsize - 8*(rm->slices - rm->cur_slice); | |
510 | |
511 rm->videobuf[0] = rm->cur_slice-1; | |
512 if(av_new_packet(pkt, ssize) < 0) | |
513 return AVERROR(ENOMEM); | |
514 memcpy(pkt->data, rm->videobuf, ssize); | |
515 return 0; | |
516 } | |
517 | |
518 return 1; | |
434 } | 519 } |
435 | 520 |
436 static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) | 521 static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) |
437 { | 522 { |
438 RMContext *rm = s->priv_data; | 523 RMContext *rm = s->priv_data; |
490 if(len<0) | 575 if(len<0) |
491 return AVERROR(EIO); | 576 return AVERROR(EIO); |
492 st = s->streams[i]; | 577 st = s->streams[i]; |
493 | 578 |
494 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | 579 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
495 int h, pic_num, len2, pos; | |
496 | |
497 h= get_byte(pb); len--; | |
498 if(!(h & 0x40)){ | |
499 seq = get_byte(pb); len--; | |
500 } | |
501 | |
502 if((h & 0xc0) == 0x40){ | |
503 len2= pos= 0; | |
504 }else{ | |
505 len2 = get_num(pb, &len); | |
506 pos = get_num(pb, &len); | |
507 } | |
508 /* picture number */ | |
509 pic_num= get_byte(pb); len--; | |
510 rm->remaining_len= len; | |
511 rm->current_stream= st->id; | 580 rm->current_stream= st->id; |
512 | 581 if(rm_assemble_video_frame(s, rm, pkt, len) == 1) |
513 // av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num); | 582 goto resync;//got partial frame |
514 if((h & 0xc0) == 0x80) | |
515 len=pos; | |
516 if(len2 && len2<len) | |
517 len=len2; | |
518 rm->remaining_len-= len; | |
519 av_get_packet(pb, pkt, len); | |
520 | |
521 } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | 583 } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { |
522 if ((st->codec->codec_id == CODEC_ID_RA_288) || | 584 if ((st->codec->codec_id == CODEC_ID_RA_288) || |
523 (st->codec->codec_id == CODEC_ID_COOK) || | 585 (st->codec->codec_id == CODEC_ID_COOK) || |
524 (st->codec->codec_id == CODEC_ID_ATRAC3)) { | 586 (st->codec->codec_id == CODEC_ID_ATRAC3)) { |
525 int x; | 587 int x; |
618 static int rm_read_close(AVFormatContext *s) | 680 static int rm_read_close(AVFormatContext *s) |
619 { | 681 { |
620 RMContext *rm = s->priv_data; | 682 RMContext *rm = s->priv_data; |
621 | 683 |
622 av_free(rm->audiobuf); | 684 av_free(rm->audiobuf); |
685 av_free(rm->videobuf); | |
623 return 0; | 686 return 0; |
624 } | 687 } |
625 | 688 |
626 static int rm_probe(AVProbeData *p) | 689 static int rm_probe(AVProbeData *p) |
627 { | 690 { |