[FFmpeg-devel] [RFC] Feed whole frames to RV* decoders
Kostya
kostya.shishkov
Tue Oct 2 07:02:59 CEST 2007
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.
-------------- next part --------------
Index: libavcodec/rv10.c
===================================================================
--- libavcodec/rv10.c (revision 10505)
+++ libavcodec/rv10.c (working copy)
@@ -718,6 +718,7 @@
MpegEncContext *s = avctx->priv_data;
int i;
AVFrame *pict = data;
+ int slice_count, *slice_offset;
#ifdef DEBUG
av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size);
@@ -729,20 +730,29 @@
}
if(avctx->slice_count){
- for(i=0; i<avctx->slice_count; i++){
- int offset= avctx->slice_offset[i];
+ slice_count = avctx->slice_count;
+ slice_offset = avctx->slice_offset;
+ }else{
+ slice_count = (*buf++) + 1;
+ slice_offset = av_malloc(sizeof(int)*slice_count);
+ for(i = 0; i < slice_count; i++){
+ buf += 4;
+ slice_offset[i] = AV_RL32(buf);
+ buf += 4;
+ }
+ }
+
+ for(i=0; i<slice_count; i++){
+ int offset= slice_offset[i];
int size;
- if(i+1 == avctx->slice_count)
+ if(i+1 == slice_count)
size= buf_size - offset;
else
- size= avctx->slice_offset[i+1] - offset;
+ size= slice_offset[i+1] - offset;
rv10_decode_packet(avctx, buf+offset, size);
}
- }else{
- rv10_decode_packet(avctx, buf, buf_size);
- }
if(s->current_picture_ptr != NULL && s->mb_y>=s->mb_height){
ff_er_frame_end(s);
Index: libavformat/matroskadec.c
===================================================================
--- libavformat/matroskadec.c (revision 10505)
+++ libavformat/matroskadec.c (working copy)
@@ -2390,8 +2390,25 @@
int slice, slices = 1;
if (real_v) {
- slices = *data++ + 1;
- lace_size[n]--;
+ pkt = av_mallocz(sizeof(AVPacket));
+ /* XXX: prevent data copy... */
+ if (av_new_packet(pkt, lace_size[n]) < 0) {
+ res = AVERROR(ENOMEM);
+ n = laces-1;
+ break;
+ }
+ memcpy (pkt->data, data, lace_size[n]);
+
+ if (n == 0)
+ pkt->flags = is_keyframe;
+ pkt->stream_index = matroska->tracks[track]->stream_index;
+
+ pkt->pts = timecode;
+ pkt->pos = pos;
+ pkt->duration = duration;
+
+ matroska_queue_packet(matroska, pkt);
+ continue;
}
for (slice=0; slice<slices; slice++) {
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 {
@@ -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;
+ slices++; //sometimes first slice report one less slice that consequent slices
+ 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);
+ 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);
+ }
+ return 0;
+}
+
static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
RMContext *rm = s->priv_data;
@@ -491,32 +601,8 @@
st = s->streams[i];
if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
- int h, pic_num, len2, pos;
-
- h= get_byte(pb); len--;
- if(!(h & 0x40)){
- seq = get_byte(pb); len--;
- }
-
- if((h & 0xc0) == 0x40){
- len2= pos= 0;
- }else{
- len2 = get_num(pb, &len);
- pos = get_num(pb, &len);
- }
- /* picture number */
- pic_num= get_byte(pb); len--;
- rm->remaining_len= len;
- rm->current_stream= st->id;
-
-// av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num);
- if((h & 0xc0) == 0x80)
- len=pos;
- if(len2 && len2<len)
- len=len2;
- rm->remaining_len-= len;
- av_get_packet(pb, pkt, len);
-
+ rm->current_stream = st->id;
+ rm_assemble_frame(s, rm, pb, pkt, len);
} else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
if ((st->codec->codec_id == CODEC_ID_RA_288) ||
(st->codec->codec_id == CODEC_ID_COOK) ||
More information about the ffmpeg-devel
mailing list