This works with PAFF and CODEC_FLAG2_CHUNKS, though the second is useless and
should be removed.
---
libavcodec/h264.c | 156 ++++++++++++++++++++++++++++------------------------
libavcodec/h264.h | 1 +
2 files changed, 85 insertions(+), 72 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 4ae4212..0ab49c3 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -2422,6 +2422,7 @@ static int decode_update_context(AVCodecContext *dst, AVCodecContext *src){
h->prev_poc_lsb= h->poc_lsb;
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
}
+ if(h->next_output_pic) h->outputed_poc = h->next_output_pic->poc;
return 0;
}
@@ -2477,6 +2478,9 @@ static int frame_start(H264Context *h){
s->current_picture_ptr->field_poc[0]=
s->current_picture_ptr->field_poc[1]= INT_MAX;
+
+ h->next_output_pic = NULL;
+
assert(s->current_picture_ptr->long_ref==0);
return 0;
@@ -6801,12 +6805,83 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
/**
* Run setup operations that must be run after slice header decoding.
- * This includes setting Picture variables and reordering output frames.
+ * This includes finding the next displayed frame.
*
* @param h h264 master context
*/
static void decode_postinit(H264Context *h){
MpegEncContext * const s = &h->s;
+ Picture *out = s->current_picture_ptr;
+ Picture *cur = s->current_picture_ptr;
+ int i, pics, cross_idr, out_of_order, out_idx;
+
+ s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
+ s->current_picture_ptr->pict_type= s->pict_type;
+
+ // Don't do anything if it's the first field or we've already been called.
+ if (h->next_output_pic || cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) return;
+
+ cur->interlaced_frame = FIELD_OR_MBAFF_PICTURE;
+ /* Derive top_field_first from field pocs. */
+ cur->top_field_first = cur->field_poc[0] < cur->field_poc[1];
+
+ //FIXME do something with unavailable reference frames
+
+ /* Sort B-frames into display order */
+
+ if(h->sps.bitstream_restriction_flag
+ && s->avctx->has_b_frames < h->sps.num_reorder_frames){
+ s->avctx->has_b_frames = h->sps.num_reorder_frames;
+ s->low_delay = 0;
+ }
+
+ if( s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
+ && !h->sps.bitstream_restriction_flag){
+ s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
+ s->low_delay= 0;
+ }
+
+ pics = 0;
+ while(h->delayed_pic[pics]) pics++;
+
+ assert(pics <= MAX_DELAYED_PIC_COUNT);
+
+ h->delayed_pic[pics++] = cur;
+ if(cur->reference == 0)
+ cur->reference = DELAYED_PIC_REF;
+
+ out = h->delayed_pic[0];
+ out_idx = 0;
+ for(i=1; h->delayed_pic[i] && h->delayed_pic[i]->poc; i++)
+ if(h->delayed_pic[i]->poc < out->poc){
+ out = h->delayed_pic[i];
+ out_idx = i;
+ }
+ cross_idr = !h->delayed_pic[0]->poc || !!h->delayed_pic[i];
+
+ out_of_order = !cross_idr && out->poc < h->outputed_poc;
+
+ if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
+ { }
+ else if((out_of_order && pics-1 == s->avctx->has_b_frames && s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT)
+ || (s->low_delay &&
+ ((!cross_idr && out->poc > h->outputed_poc + 2)
+ || cur->pict_type == FF_B_TYPE)))
+ {
+ s->low_delay = 0;
+ s->avctx->has_b_frames++;
+ }
+
+ if(out_of_order || pics > s->avctx->has_b_frames){
+ out->reference &= ~DELAYED_PIC_REF;
+ for(i=out_idx; h->delayed_pic[i]; i++)
+ h->delayed_pic[i] = h->delayed_pic[i+1];
+ }
+ if(!out_of_order && pics > s->avctx->has_b_frames){
+ h->next_output_pic = out;
+ }else{
+ av_log(s->avctx, AV_LOG_DEBUG, "no picture\n");
+ }
ff_report_predecode_done(s->avctx);
}
@@ -7487,6 +7562,8 @@ static void execute_decode_slices(H264Context *h, int context_count){
H264Context *hx;
int i;
+ if(!(s->flags2 & CODEC_FLAG2_CHUNKS)) decode_postinit(h);
+
if(context_count == 1) {
decode_slice(avctx, h);
} else {
@@ -7801,16 +7878,12 @@ static int decode_frame(AVCodecContext *avctx,
}
if(!(s->flags2 & CODEC_FLAG2_CHUNKS) || (s->mb_y >= s->mb_height && s->mb_height)){
- Picture *out = s->current_picture_ptr;
- Picture *cur = s->current_picture_ptr;
- int i, pics, cross_idr, out_of_order, out_idx;
+
+ if(s->flags2 & CODEC_FLAG2_CHUNKS) decode_postinit(h);
s->mb_y= 0;
ff_report_decode_progress((AVFrame*)s->current_picture_ptr, (16*s->mb_height >> s->first_field) - 1);
- s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
- s->current_picture_ptr->pict_type= s->pict_type;
-
if(!USE_FRAME_THREADING(avctx)){
if(!s->dropable) {
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
@@ -7819,6 +7892,7 @@ static int decode_frame(AVCodecContext *avctx,
}
h->prev_frame_num_offset= h->frame_num_offset;
h->prev_frame_num= h->frame_num;
+ if(h->next_output_pic) h->outputed_poc = h->next_output_pic->poc;
}
/*
@@ -7838,75 +7912,13 @@ static int decode_frame(AVCodecContext *avctx,
MPV_frame_end(s);
- if (cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) {
+ if (!h->next_output_pic) {
/* Wait for second field. */
*data_size = 0;
} else {
- cur->interlaced_frame = FIELD_OR_MBAFF_PICTURE;
- /* Derive top_field_first from field pocs. */
- cur->top_field_first = cur->field_poc[0] < cur->field_poc[1];
-
- //FIXME do something with unavailable reference frames
-
- /* Sort B-frames into display order */
-
- if(h->sps.bitstream_restriction_flag
- && s->avctx->has_b_frames < h->sps.num_reorder_frames){
- s->avctx->has_b_frames = h->sps.num_reorder_frames;
- s->low_delay = 0;
- }
-
- if( s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
- && !h->sps.bitstream_restriction_flag){
- s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
- s->low_delay= 0;
- }
-
- pics = 0;
- while(h->delayed_pic[pics]) pics++;
-
- assert(pics <= MAX_DELAYED_PIC_COUNT);
-
- h->delayed_pic[pics++] = cur;
- if(cur->reference == 0)
- cur->reference = DELAYED_PIC_REF;
-
- out = h->delayed_pic[0];
- out_idx = 0;
- for(i=1; h->delayed_pic[i] && h->delayed_pic[i]->poc; i++)
- if(h->delayed_pic[i]->poc < out->poc){
- out = h->delayed_pic[i];
- out_idx = i;
- }
- cross_idr = !h->delayed_pic[0]->poc || !!h->delayed_pic[i];
-
- out_of_order = !cross_idr && out->poc < h->outputed_poc;
-
- if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
- { }
- else if((out_of_order && pics-1 == s->avctx->has_b_frames && s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT)
- || (s->low_delay &&
- ((!cross_idr && out->poc > h->outputed_poc + 2)
- || cur->pict_type == FF_B_TYPE)))
- {
- s->low_delay = 0;
- s->avctx->has_b_frames++;
- }
-
- if(out_of_order || pics > s->avctx->has_b_frames){
- out->reference &= ~DELAYED_PIC_REF;
- for(i=out_idx; h->delayed_pic[i]; i++)
- h->delayed_pic[i] = h->delayed_pic[i+1];
- }
- if(!out_of_order && pics > s->avctx->has_b_frames){
- *data_size = sizeof(AVFrame);
-
- h->outputed_poc = out->poc;
- *pict= *(AVFrame*)out;
- }else{
- av_log(avctx, AV_LOG_DEBUG, "no picture\n");
- }
+ *data_size = sizeof(AVFrame);
+ *pict = *(AVFrame*)h->next_output_pic;
}
}
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 39a0a27..c251da3 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -348,6 +348,7 @@ typedef struct H264Context{
according to picture reordering in slice header */
int ref2frm[16][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1
Picture *delayed_pic[MAX_DELAYED_PIC_COUNT+2]; //FIXME size?
+ Picture *next_output_pic;
int outputed_poc;
/**
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc