[FFmpeg-devel] [PATCH] Implement PAFF in H.264
Jeff Downs
heydowns
Tue Sep 25 21:51:11 CEST 2007
On Mon, 24 Sep 2007, Jeff Downs wrote:
> On Mon, 24 Sep 2007, Michael Niedermayer wrote:
> >
> > IMHO the AVFrame.reference code should be fixed first unless this turns
> > out to be very complex to fix
> >
>
> OK. I took a second look at how Picture.reference is used in mpegvideo.c
> and h264.c. For current SVN (no PAFF), its not too difficult to fix
> (replace use of reference = 1 with 4 as suggested).
>
>
> When PAFF is considered, two problems present:
>
> First, a place to store a second field's "is a reference" flag is needed,
> separate from the reference marking of the first field in a pair.
>
> Would using s->dropable for this be an acceptable solution? Or should
> I continue with current_picture.reference?
>
> This way:
>
> s->dropable == current field or frame needs reference marking when
> complete.
>
> current_picture.(_ptr->)reference == PICT_XXX, or 4, as dictated by
> and set in reference picture marking process and delayed picture holding.
>
>
> Second, MPV_frame_start forces a value of 3 onto reference for ref frames.
> This could be solved by replacing "3" with s->picture_structure. But that
> doesn't really make complete sense for mpeg2.
>
> Another option is to let MPV_frame_start still set 3, but override in
> h264 with picture_structure.
>
> Another option still is to override with zero, and then let the frame end
> processing (ref marking and pic output) take total control of the
> reference variable handling. This is good because it isolates reference
> handling to one area.
>
Attached is a patch that cleans up handling of Picture.reference in h264
using some of the above-described approach.
I decided to change MPV_frame_start to use s->picture_structure for
reference in h264 case because it was already testing for h264 there
anyway. This prepares for PAFF implementation.
This also makes current_picture.reference necessarily ==
current_picture_ptr->reference and updates any tests of either to have
field references in mind.
If ok, I will update PAFF implementation based on this.
-Jeff
-------------- next part --------------
Index: libavcodec/h264.c
===================================================================
--- libavcodec/h264.c (revision 10573)
+++ libavcodec/h264.c (working copy)
@@ -38,6 +38,12 @@
//#undef NDEBUG
#include <assert.h>
+/*
+ * Value of Picture.reference when Picture is not a reference picture, but
+ * is held for delayed output.
+ */
+#define DELAYED_PIC_REF 4
+
static VLC coeff_token_vlc[4];
static VLC chroma_dc_coeff_token_vlc;
@@ -3091,11 +3097,11 @@
int i;
pic->reference=0;
if(pic == h->delayed_output_pic)
- pic->reference=1;
+ pic->reference=DELAYED_PIC_REF;
else{
for(i = 0; h->delayed_pic[i]; i++)
if(pic == h->delayed_pic[i]){
- pic->reference=1;
+ pic->reference=DELAYED_PIC_REF;
break;
}
}
@@ -3542,7 +3548,6 @@
unsigned int slice_type, tmp, i;
int default_ref_list_done = 0;
- s->current_picture.reference= h->nal_ref_idc != 0;
s->dropable= h->nal_ref_idc == 0;
first_mb_in_slice= get_ue_golomb(&s->gb);
@@ -3652,14 +3657,6 @@
}
}
- if(h0->current_slice == 0){
- if(frame_start(h) < 0)
- return -1;
- }
- if(h != h0)
- clone_slice(h, h0);
-
- s->current_picture_ptr->frame_num= //FIXME frame_num cleanup
h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num);
h->mb_mbaff = 0;
@@ -3675,6 +3672,16 @@
h->mb_aff_frame = h->sps.mb_aff;
}
}
+
+ if(h0->current_slice == 0){
+ if(frame_start(h) < 0)
+ return -1;
+ }
+ if(h != h0)
+ clone_slice(h, h0);
+
+ s->current_picture_ptr->frame_num= h->frame_num; //FIXME frame_num cleanup
+
assert(s->mb_num == s->mb_width * s->mb_height);
if(first_mb_in_slice << h->mb_aff_frame >= s->mb_num ||
first_mb_in_slice >= s->mb_num){
@@ -3763,7 +3770,7 @@
else
h->use_weight = 0;
- if(s->current_picture.reference)
+ if(h->nal_ref_idc)
decode_ref_pic_marking(h0, &s->gb);
if(FRAME_MBAFF)
@@ -3863,7 +3870,7 @@
);
}
- if((s->avctx->flags2 & CODEC_FLAG2_FAST) && !s->current_picture.reference){
+ if((s->avctx->flags2 & CODEC_FLAG2_FAST) && !h->nal_ref_idc){
s->me.qpel_put= s->dsp.put_2tap_qpel_pixels_tab;
s->me.qpel_avg= s->dsp.avg_2tap_qpel_pixels_tab;
}else{
@@ -7361,12 +7368,11 @@
h->prev_frame_num_offset= h->frame_num_offset;
h->prev_frame_num= h->frame_num;
- if(s->current_picture_ptr->reference){
+ if(s->current_picture_ptr->reference & s->picture_structure){
h->prev_poc_msb= h->poc_msb;
h->prev_poc_lsb= h->poc_lsb;
+ execute_ref_pic_marking(h, h->mmco, h->mmco_index);
}
- if(s->current_picture_ptr->reference)
- execute_ref_pic_marking(h, h->mmco, h->mmco_index);
ff_er_frame_end(s);
@@ -7392,7 +7398,7 @@
h->delayed_pic[pics++] = cur;
if(cur->reference == 0)
- cur->reference = 1;
+ cur->reference = DELAYED_PIC_REF;
cross_idr = 0;
for(i=0; h->delayed_pic[i]; i++)
@@ -7433,7 +7439,7 @@
*data_size = 0;
else
*data_size = sizeof(AVFrame);
- if(prev && prev != out && prev->reference == 1)
+ if(prev && prev != out && prev->reference == DELAYED_PIC_REF)
prev->reference = 0;
h->delayed_output_pic = out;
#endif
Index: libavcodec/mpegvideo.c
===================================================================
--- libavcodec/mpegvideo.c (revision 10573)
+++ libavcodec/mpegvideo.c (working copy)
@@ -907,8 +907,13 @@
pic= (AVFrame*)&s->picture[i];
}
- pic->reference= (s->pict_type != B_TYPE || s->codec_id == CODEC_ID_H264)
- && !s->dropable ? 3 : 0;
+ pic->reference= 0;
+ if (!s->dropable){
+ if (s->codec_id == CODEC_ID_H264)
+ pic->reference = s->picture_structure;
+ else if (s->pict_type != B_TYPE)
+ pic->reference = 3;
+ }
pic->coded_picture_number= s->coded_picture_number++;
More information about the ffmpeg-devel
mailing list