[FFmpeg-devel] [RFC, PATCH] RealVideo full-frame demux/decode
Roberto Togni
rxt
Sun Oct 21 15:59:52 CEST 2007
On Sat, 20 Oct 2007 16:14:08 +0300
Kostya <kostya.shishkov at gmail.com> wrote:
> Here is another attempt on making lavc RV decoder work
> with full frames instead of slices.
>
> Attached patches:
> 0. RM demuxer
> 1. RV10/20 decoder patch to make it work with slices
> 2. Indentation after patch #1
>
> Some notes on demuxer: as at least one sample shows that
> video frame slices may be interleaved with audio slices
> I store them in special buffer and make packet only when
> all data for single frame is gathered.
> Index: libavformat/rm.h
> ===================================================================
> --- libavformat/rm.h (revision 10722)
> +++ libavformat/rm.h (working copy)
> @@ -46,6 +46,9 @@
> int old_format;
> int current_stream;
> int remaining_len;
> + uint8_t *videobuf; ///< place to store merged video frame
> + int videobufsize; ///< current assembled frame size
> + int cur_slice, slices;
> /// Audio descrambling matrix parameters
> uint8_t *audiobuf; ///< place to store reordered audio data
> int64_t audiotimestamp; ///< Audio packet timestamp
> Index: libavformat/rmdec.c
> ===================================================================
> --- libavformat/rmdec.c (revision 10722)
> +++ libavformat/rmdec.c (working copy)
> @@ -365,6 +365,7 @@
>
> n = get_be16(pb);
> (*len)-=2;
> + n &= 0x7FFF;
> if (n >= 0x4000) {
> return n - 0x4000;
> } else {
> @@ -433,6 +434,81 @@
> return -1;
> }
>
> +static int rm_assemble_video_frame(AVFormatContext *s, RMContext
> *rm, AVPacket *pkt, int len) +{
> + ByteIOContext *pb = &s->pb;
> + int hdr, seq, pic_num, len2, pos;
> + int type;
> + int ssize;
> +
> + hdr = get_byte(pb); len--;
> + type = hdr >> 6;
> + switch(type){
> + case 0: // slice
> + case 2: // last slice
> + seq = get_byte(pb); len--;
> + len2 = get_num(pb, &len);
> + pos = get_num(pb, &len);
> + pic_num = get_byte(pb); len--;
> + rm->remaining_len = len;
> + break;
> + case 1: //whole frame
> + seq = get_byte(pb); len--;
> + if(av_new_packet(pkt, len + 9) < 0)
> + return AVERROR(EIO);
> + pkt->data[0] = 0;
> + AV_WL32(pkt->data + 1, 1);
> + AV_WL32(pkt->data + 5, 0);
> + get_buffer(pb, pkt->data + 9, len);
> + rm->remaining_len = 0;
> + return 0;
> + case 3: //frame as a part of packet
> + len2 = get_num(pb, &len);
> + pos = get_num(pb, &len);
> + pic_num = get_byte(pb); len--;
> + rm->remaining_len = len - len2;
> + if(av_new_packet(pkt, len2 + 9) < 0)
> + return AVERROR(EIO);
> + pkt->data[0] = 0;
> + AV_WL32(pkt->data + 1, 1);
> + AV_WL32(pkt->data + 5, 0);
> + get_buffer(pb, pkt->data + 9, len2);
> + return 0;
> + }
> + //now we have to deal with single slice
> + rm->cur_slice = seq & 0x7F;
> + rm->slices = ((hdr & 0x3F) << 1) + 1;
> +
> + if(rm->cur_slice == 1){//XXX: maybe enable for all slices?
Maybe reinint also on pic_num change.
> + ssize = len2 + 8*rm->slices + 1;
> + rm->videobuf = av_realloc(rm->videobuf, ssize);
> + rm->videobufsize = ssize;
> + }
> + if(type == 2){
> + len = FFMIN(len, pos);
> + pos = len2 - pos;
> + }
> +
> + AV_WL32(rm->videobuf - 7 + 8*rm->cur_slice, 1);
> + AV_WL32(rm->videobuf - 3 + 8*rm->cur_slice, pos);
Can this write out of the buffer in case of errors? I'm thinking about
a case where cur_slice is big and len2 and rm->slices are small.
Also if a slice is missing the slice table will have some
uninitialized values.
> + get_buffer(pb, rm->videobuf + 1 + 8*rm->slices + pos, len);
This could be dangerous, since the rm->slices used here is not the same
used to allocate the buffer. Also pos could be anything.
> + rm->remaining_len-= len;
> +
> + if(type == 2 || (pos + len + 1 + 8*rm->slices) ==
> rm->videobufsize){
> + //adjust slice headers
> + memmove(rm->videobuf + 1 + 8*rm->cur_slice, rm->videobuf +
> 1 + 8*rm->slices, rm->videobufsize - 1 - 8*rm->slices);
> + ssize = rm->videobufsize - 8*(rm->slices - rm->cur_slice);
> +
> + rm->videobuf[0] = rm->cur_slice-1;
> + if(av_new_packet(pkt, ssize) < 0)
> + return AVERROR(ENOMEM);
> + memcpy(pkt->data, rm->videobuf, ssize);
> + return 0;
> + }
> +
> + return 1;
> +}
> +
Maybe the easiest solution is to use always the slice number from the
first slice and just use a counter for the cur_slice number (ignoring
the value from the header) and write slices in sequence (ignoring pos).
> static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
[...]
Can you test the attached patch? I only tested with rv10/20. This
should address all the issues.
For all the rest patch ok, and thanks for taking care of this.
Ciao,
Roberto
--
Better is the enemy of good enough.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: slicedmx.diff
Type: text/x-patch
Size: 5393 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20071021/09c82a01/attachment.bin>
More information about the ffmpeg-devel
mailing list