[FFmpeg-devel] [RFC] Feed whole frames to RV* decoders
Roberto Togni
rxt
Tue Oct 9 00:18:59 CEST 2007
On Tue, 2 Oct 2007 08:02:59 +0300
Kostya <kostya.shishkov at gmail.com> wrote:
> Here is an updated working version of gathering complete frames
> for Real Video decoders. Both RM and Matroska demuxers are passing
> whole frames to RealVideo decoder (RV10/20 is patched to accept
> this format).
>
> Please comment.
Sorry for the late review. I haven't tested the patch, but look mostly
ok. See below.
As a side note, the format chosen for the video frame is compatible
with matroska, files but does not contain the frame timestamp from the
data packet header; unless the binary codecs can work without it the
demuxer will be incompatible with them.
> Index: libavformat/rmdec.c
> ===================================================================
> --- libavformat/rmdec.c (revision 10505)
> +++ libavformat/rmdec.c (working copy)
> @@ -364,6 +364,10 @@
>
> n = get_be16(pb);
> (*len)-=2;
> + if (n >= 0x8000) {
> + av_log(NULL,0,"Got number %X\n",n);
> + n -= 0x8000;
> + }
> if (n >= 0x4000) {
> return n - 0x4000;
> } else {
Maybe if(n & 0xc000) return n & 0x3fff; your version is ok too if you
prefer it, but I'd remove the av_log().
> @@ -432,6 +436,112 @@
> return -1;
> }
>
> +static int rm_assemble_frame(AVFormatContext *s, RMContext *rm,
> ByteIOContext *pb, AVPacket *pkt, int len) +{
> + int hdr, type, seq, pic_num, pkt_len, pos, frame_length, ret;
> + int slices, slice_count;
> + uint8_t *slice_hdr, *slice_data, *slice_data_start, *data_end;
> + int flags, idx;
> + int64_t timestamp, pos2;
> +
> + hdr = get_byte(pb); len--;
> + type = hdr >> 6;
> +
> + switch (type) {
> + case 0: // partial frame start
> + case 2: // partial frame end - should not happen here
> + seq = get_byte(pb); len--;
> + pkt_len = get_num(pb, &len);
> + pos = get_num(pb, &len);
> + pic_num = get_byte(pb); len--;
> + frame_length = len;
> + slices = (((hdr << 8) | seq) >> 7) & 0x7F;
Shouldn't this be (hdr << 1) ?
> + slices++; //sometimes first slice report one less slice that
> consequent slices
Are you sure about the slice number calculation? MPlayer demuxer does
(hdr & 0x3f)*2, and the number of slices is always one less than the
real number.
> + break;
> + case 1: // whole frame
> + pic_num = get_byte(pb); len--;
> + pos = 0;
> + frame_length = pkt_len = len;
> + slices = 1;
> + break;
> + case 3: // one of multiple frames in one packet
> + pkt_len = get_num(pb, &len);
> + pos = get_num(pb, &len);
> + pic_num = get_byte(pb); len--;
> + frame_length = pkt_len;
> + slices = 1;
> + break;
> + }
> +
> + if (type == 2) //frame tail should not be met here
> + return -1;
> +
> + if(av_new_packet(pkt, pkt_len + slices * 8 + 1))
> + return AVERROR(ENOMEM);
> + slice_hdr = pkt->data + 1;
> + slice_data = slice_data_start = slice_hdr + slices * 8;
> + data_end = pkt->data + pkt_len + slices * 8 + 1;
> +
> + pkt->data[0] = slices - 1;
> +
> + AV_WL32(slice_hdr + 0, 1);
> + AV_WL32(slice_hdr + 4, 0);
> + slice_hdr += 8;
> + ret = get_buffer(pb, slice_data, frame_length);
> + if (ret != frame_length) {
> + av_free_packet(pkt);
> + return AVERROR(EIO);
> + }
> + slice_data += frame_length;
> + slice_count = 1;
> + rm->remaining_len = len - frame_length;
> + while(slice_data < data_end && slice_count < slices) {
> + len=sync(s, ×tamp, &flags, &idx, &pos2);
This will work only if there are no audio packet mixed with the parts
of the video frame, but I guess this is ok for real vorld, video
packets were grouped together in the files I checked.
> + if (len<0) {
> + av_free_packet(pkt);
> + return AVERROR(EIO);
> + }
> +
> + hdr = get_byte(pb); len--;
> + type = hdr >> 6;
> + seq = get_byte(pb); len--;
> + pkt_len = get_num(pb, &len);
> + pos = get_num(pb, &len);
> + pic_num = get_byte(pb); len--;
> +
> + if (type == 2) {
> + rm->remaining_len = len - pos;
> + frame_length = pos;
> + } else {
> + frame_length = len;
> + }
> + if (slice_data + frame_length > data_end) {
> + av_free_packet(pkt);
> + return AVERROR(EIO);
> + }
> +
> + AV_WL32(slice_hdr + 0, 1);
> + AV_WL32(slice_hdr + 4, slice_data - slice_data_start);
> + slice_hdr += 8;
> +
> + ret = get_buffer(pb, slice_data, frame_length);
> + if (ret != frame_length) {
> + av_free_packet(pkt);
> + return AVERROR(EIO);
> + }
> + slice_data += frame_length;
> + slice_count++;
> + if (type == 2)
> + break;
> + }
> + if(slice_count < slices){
> + pkt->data[0] = slice_count - 1;
> + memmove(slice_hdr, slice_hdr+8*(slices - slice_count),
> pkt->size - 1 - 8*slices);
> + pkt->size -= 8*(slices - slice_count);
> + }
If the slice number thing can be solved this can probably be removed.
> + return 0;
> +}
> +
> static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
> {
> RMContext *rm = s->priv_data;
[...]
There is no error checking for out of sequence slices, incomplete
packets or similar things, but those can be added later.
Ciao,
Roberto
--
Better is the enemy of good enough.
More information about the ffmpeg-devel
mailing list