[FFmpeg-devel] [PATCH] Implement PAFF in H.264
Jeff Downs
heydowns
Tue Oct 2 17:57:15 CEST 2007
On Tue, 2 Oct 2007, Andreas ?man wrote:
> First two patches applied, (previously ok'ed by Michael)
>
> I fixed the doxygen incompat stuff and some vertical alignment.
Thanks. Does multiple trailing documentation lines with ///< not work
properly?
The doxy manual implied that it did.
> > - const int pic_height = 16*s->mb_height >> MB_MBAFF;
> > + const int pic_height = 16*s->mb_height >> (MB_MBAFF || FIELD_PICTURE);
>
> I believe you should use MB_FIELD here instead (and on all other places)
> Perhaps that should be a separate patch, i dunno really..
Yes, that would work as well. I did it this way to be consistent with how
it was currently being done. MB_FIELD would be a little faster at runtime.
I can post a new patch with this change, or provide one to do it
after, depending on the desired order of things. Stronger opinions anyone?
> > @@ -4835,19 +5209,13 @@
> > if( cbp_a == 2 ) ctx++;
> > if( cbp_b == 2 ) ctx += 2;
> > return 1 + get_cabac_noinline( &h->cabac, &h->cabac_state[77 + ctx] );
> > }
> > static int decode_cabac_mb_dqp( H264Context *h) {
> > - MpegEncContext * const s = &h->s;
> > - int mbn_xy;
> > int ctx = 0;
> > int val = 0;
> >
> > - if( s->mb_x > 0 )
> > - mbn_xy = s->mb_x + s->mb_y*s->mb_stride - 1;
> > - else
> > - mbn_xy = s->mb_width - 1 + (s->mb_y-1)*s->mb_stride;
> >
> > if( h->last_qscale_diff != 0 )
> > ctx++;
> >
> > while( get_cabac_noinline( &h->cabac, &h->cabac_state[60 + ctx] ) ) {
>
> Unrelated removal of unused code, but deserves to be fixed either way.
Yes. My mistake - I meant to remove that hunk prior to posting.
Patch w/out that hunk attached.
Thanks for taking a look.
-Jeff
-------------- next part --------------
--- ../ffmpeg-cosmetics/libavcodec/h264.c 2007-10-01 14:02:06.000000000 -0400
+++ libavcodec/h264.c 2007-10-01 15:56:22.000000000 -0400
@@ -175,11 +175,11 @@
if(for_deblock && (h->slice_num == 1 || h->slice_table[mb_xy] == h->slice_table[mb_xy-s->mb_stride]) && !FRAME_MBAFF)
return;
//wow what a mess, why didn't they simplify the interlacing&intra stuff, i can't imagine that these complex rules are worth it
- top_xy = mb_xy - s->mb_stride;
+ top_xy = mb_xy - (s->mb_stride << FIELD_PICTURE);
topleft_xy = top_xy - 1;
topright_xy= top_xy + 1;
left_xy[1] = left_xy[0] = mb_xy-1;
left_block[0]= 0;
left_block[1]= 1;
@@ -1701,11 +1701,11 @@
int extra_height= h->emu_edge_height;
int emu=0;
const int full_mx= mx>>2;
const int full_my= my>>2;
const int pic_width = 16*s->mb_width;
- const int pic_height = 16*s->mb_height >> MB_MBAFF;
+ const int pic_height = 16*s->mb_height >> (MB_MBAFF || FIELD_PICTURE);
if(!pic->data[0]) //FIXME this is unacceptable, some senseable error concealment must be done for missing reference frames
return;
if(mx&7) extra_width -= 3;
@@ -1725,11 +1725,11 @@
qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize);
}
if(ENABLE_GRAY && s->flags&CODEC_FLAG_GRAY) return;
- if(MB_MBAFF){
+ if(MB_MBAFF || FIELD_PICTURE){
// chroma offset when predicting from a field of opposite parity
my += 2 * ((s->mb_y & 1) - (h->ref_cache[list][scan8[n]] & 1));
emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
}
src_cb= pic->data[1] + (mx>>3) + (my>>3)*h->mb_uvlinesize;
@@ -1760,11 +1760,11 @@
dest_y += 2*x_offset + 2*y_offset*h-> mb_linesize;
dest_cb += x_offset + y_offset*h->mb_uvlinesize;
dest_cr += x_offset + y_offset*h->mb_uvlinesize;
x_offset += 8*s->mb_x;
- y_offset += 8*(s->mb_y >> MB_MBAFF);
+ y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE));
if(list0){
Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ];
mc_dir_part(h, ref, n, square, chroma_height, delta, 0,
dest_y, dest_cb, dest_cr, x_offset, y_offset,
@@ -1793,11 +1793,11 @@
dest_y += 2*x_offset + 2*y_offset*h-> mb_linesize;
dest_cb += x_offset + y_offset*h->mb_uvlinesize;
dest_cr += x_offset + y_offset*h->mb_uvlinesize;
x_offset += 8*s->mb_x;
- y_offset += 8*(s->mb_y >> MB_MBAFF);
+ y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE));
if(list0 && list1){
/* don't optimize for luma-only case, since B-frames usually
* use implicit weights => chroma too. */
uint8_t *tmp_cb = s->obmc_scratchpad;
@@ -2247,10 +2247,11 @@
int i;
if(MPV_frame_start(s, s->avctx) < 0)
return -1;
ff_er_frame_start(s);
+ s->current_picture_ptr->key_frame= 0;
assert(s->linesize && s->uvlinesize);
for(i=0; i<16; i++){
h->block_offset[i]= 4*((scan8[i] - scan8[0])&7) + 4*s->linesize*((scan8[i] - scan8[0])>>3);
@@ -2755,20 +2756,138 @@
if (is_complex)
hl_decode_mb_complex(h);
else hl_decode_mb_simple(h);
}
+static void pic_as_field(Picture *pic, const int bottom){
+ int i;
+ for (i = 0; i < 4; ++i) {
+ if (bottom)
+ pic->data[i] += pic->linesize[i];
+ pic->linesize[i] *= 2;
+ }
+}
+
+static int split_field_copy(Picture *dest, Picture *src,
+ int parity, int id_add){
+ int match = (src->reference & parity) != 0;
+
+ if (match) {
+ *dest = *src;
+ pic_as_field(dest, parity == PICT_BOTTOM_FIELD);
+ dest->pic_id *= 2;
+ dest->pic_id += id_add;
+ }
+
+ return match;
+}
+
+/**
+ * Split one reference list into field parts, interleaving by parity
+ * as per H.264 spec section 8.2.4.2.5. Output fields have their data pointers
+ * set to look at the actual start of data for that field.
+ *
+ * @param dest output list
+ * @param dest_len maximum number of fields to put in dest
+ * @param src the source reference list containing fields and/or field pairs
+ * (aka short_ref/long_ref, or
+ * refFrameListXShortTerm/refFrameListLongTerm in spec-speak)
+ * @param src_len number of Picture's in source (pairs and unmatched fields)
+ * @param parity the parity of the picture being decoded/needing
+ * these ref pics (PICT_{TOP,BOTTOM}_FIELD)
+ * @return number of fields placed in dest
+ */
+static int split_field_half_ref_list(Picture *dest, int dest_len,
+ Picture *src, int src_len, int parity){
+ int same_i, opp_i;
+ int i;
+ int same;
+ int out_i;
+
+ same_i = 0;
+ opp_i = 0;
+ same = 1;
+ out_i = 0;
+
+ while (out_i < dest_len) {
+ if (same && same_i < src_len) {
+ i = split_field_copy(dest + out_i, src + same_i, parity, 1);
+ same = !i;
+ same_i++;
+
+ } else if (opp_i < src_len) {
+ i = split_field_copy(dest + out_i, src + opp_i,
+ PICT_FRAME - parity, 0);
+ same = i;
+ opp_i++;
+
+ } else {
+ break;
+ }
+ out_i += i;
+ }
+
+ return out_i;
+}
+
+/**
+ * Split the reference frame list into a reference field list.
+ * This implements H.264 spec 8.2.4.2.5 for a combined input list.
+ * The input list contains both reference field pairs and
+ * unmatched reference fields; it is ordered as spec describes
+ * RefPicListX for frames in 8.2.4.2.1 and 8.2.4.2.3, except that
+ * unmatched field pairs are also present. Conceptually this is equivalent
+ * to concatenation of refFrameListXShortTerm with refFrameListLongTerm.
+ *
+ * @param dest output reference list where ordered fields are to be placed
+ * @param dest_len max number of fields to place at dest
+ * @param src source reference list, as described above
+ * @param src_len number of pictures (pairs and unmatched fields) in src
+ * @param parity parity of field being currently decoded
+ * (one of PICT_{TOP,BOTTOM}_FIELD)
+ * @param long_i index into src array that holds first long reference picture,
+ * or src_len if no long refs present.
+ */
+static int split_field_ref_list(Picture *dest, int dest_len,
+ Picture *src, int src_len,
+ int parity, int long_i){
+
+ int i = split_field_half_ref_list(dest, dest_len, src, long_i, parity);
+ dest += i;
+ dest_len -= i;
+
+ i += split_field_half_ref_list(dest, dest_len, src + long_i,
+ src_len - long_i, parity);
+ return i;
+}
+
/**
* fills the default_ref_list.
*/
static int fill_default_ref_list(H264Context *h){
MpegEncContext * const s = &h->s;
int i;
int smallest_poc_greater_than_current = -1;
+ int structure_sel;
Picture sorted_short_ref[32];
+ Picture field_entry_list[2][32];
+ Picture *frame_list[2];
+
+ if (!FIELD_PICTURE) {
+ structure_sel = 0;
+ frame_list[0] = h->default_ref_list[0];
+ frame_list[1] = h->default_ref_list[1];
+ } else {
+ structure_sel = PICT_FRAME;
+ frame_list[0] = field_entry_list[0];
+ frame_list[1] = field_entry_list[1];
+ }
if(h->slice_type==B_TYPE){
+ int list;
+ int len[2];
+ int short_len[2];
int out_i;
int limit= INT_MIN;
/* sort frame according to poc in B slice */
for(out_i=0; out_i<h->short_ref_count; out_i++){
@@ -2792,75 +2911,97 @@
if (h->short_ref[best_i]->poc >= s->current_picture_ptr->poc) {
smallest_poc_greater_than_current = out_i;
}
}
}
- }
- if(s->picture_structure == PICT_FRAME){
- if(h->slice_type==B_TYPE){
- int list;
tprintf(h->s.avctx, "current poc: %d, smallest_poc_greater_than_current: %d\n", s->current_picture_ptr->poc, smallest_poc_greater_than_current);
// find the largest poc
for(list=0; list<2; list++){
int index = 0;
int j= -99;
int step= list ? -1 : 1;
for(i=0; i<h->short_ref_count && index < h->ref_count[list]; i++, j+=step) {
+ int sel;
while(j<0 || j>= h->short_ref_count){
if(j != -99 && step == (list ? -1 : 1))
return -1;
step = -step;
j= smallest_poc_greater_than_current + (step>>1);
}
- if(sorted_short_ref[j].reference != 3) continue;
- h->default_ref_list[list][index ]= sorted_short_ref[j];
- h->default_ref_list[list][index++].pic_id= sorted_short_ref[j].frame_num;
+ sel = sorted_short_ref[j].reference | structure_sel;
+ if(sel != PICT_FRAME) continue;
+ frame_list[list][index ]= sorted_short_ref[j];
+ frame_list[list][index++].pic_id= sorted_short_ref[j].frame_num;
}
+ short_len[list] = index;
for(i = 0; i < 16 && index < h->ref_count[ list ]; i++){
+ int sel;
if(h->long_ref[i] == NULL) continue;
- if(h->long_ref[i]->reference != 3) continue;
+ sel = h->long_ref[i]->reference | structure_sel;
+ if(sel != PICT_FRAME) continue;
- h->default_ref_list[ list ][index ]= *h->long_ref[i];
- h->default_ref_list[ list ][index++].pic_id= i;;
+ frame_list[ list ][index ]= *h->long_ref[i];
+ frame_list[ list ][index++].pic_id= i;;
}
+ len[list] = index;
if(list && (smallest_poc_greater_than_current<=0 || smallest_poc_greater_than_current>=h->short_ref_count) && (1 < index)){
// swap the two first elements of L1 when
// L0 and L1 are identical
- Picture temp= h->default_ref_list[1][0];
- h->default_ref_list[1][0] = h->default_ref_list[1][1];
- h->default_ref_list[1][1] = temp;
+ Picture temp= frame_list[1][0];
+ frame_list[1][0] = frame_list[1][1];
+ frame_list[1][1] = temp;
}
- if(index < h->ref_count[ list ])
- memset(&h->default_ref_list[list][index], 0, sizeof(Picture)*(h->ref_count[ list ] - index));
}
+
+ for(list=0; list<2; list++){
+ if (s->picture_structure != PICT_FRAME)
+ len[list] = split_field_ref_list(h->default_ref_list[list],
+ h->ref_count[list],
+ frame_list[list],
+ len[list],
+ s->picture_structure,
+ short_len[list]);
+
+ if(len[list] < h->ref_count[ list ])
+ memset(&h->default_ref_list[list][len[list]], 0, sizeof(Picture)*(h->ref_count[ list ] - len[list]));
+ }
+
+
}else{
int index=0;
+ int short_len;
for(i=0; i<h->short_ref_count; i++){
- if(h->short_ref[i]->reference != 3) continue; //FIXME refernce field shit
- h->default_ref_list[0][index ]= *h->short_ref[i];
- h->default_ref_list[0][index++].pic_id= h->short_ref[i]->frame_num;
+ int sel;
+ sel = h->short_ref[i]->reference | structure_sel;
+ if(sel != PICT_FRAME) continue;
+ frame_list[0][index ]= *h->short_ref[i];
+ frame_list[0][index++].pic_id= h->short_ref[i]->frame_num;
}
+ short_len = index;
for(i = 0; i < 16; i++){
+ int sel;
if(h->long_ref[i] == NULL) continue;
- if(h->long_ref[i]->reference != 3) continue;
- h->default_ref_list[0][index ]= *h->long_ref[i];
- h->default_ref_list[0][index++].pic_id= i;;
+ sel = h->long_ref[i]->reference | structure_sel;
+ if(sel != PICT_FRAME) continue;
+ frame_list[0][index ]= *h->long_ref[i];
+ frame_list[0][index++].pic_id= i;;
}
+
+ if (s->picture_structure != PICT_FRAME)
+ index = split_field_ref_list(h->default_ref_list[0],
+ h->ref_count[0], frame_list[0],
+ index, s->picture_structure,
+ short_len);
+
if(index < h->ref_count[0])
memset(&h->default_ref_list[0][index], 0, sizeof(Picture)*(h->ref_count[0] - index));
- }
- }else{ //FIELD
- if(h->slice_type==B_TYPE){
- }else{
- //FIXME second field balh
- }
}
#ifdef TRACE
for (i=0; i<h->ref_count[0]; i++) {
tprintf(h->s.avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].data[0]);
}
@@ -2876,11 +3017,11 @@
static void print_short_term(H264Context *h);
static void print_long_term(H264Context *h);
static int decode_ref_pic_list_reordering(H264Context *h){
MpegEncContext * const s = &h->s;
- int list, index;
+ int list, index, pic_structure;
print_short_term(h);
print_long_term(h);
if(h->slice_type==I_TYPE || h->slice_type==SI_TYPE) return 0; //FIXME move before func
@@ -2903,41 +3044,78 @@
av_log(h->s.avctx, AV_LOG_ERROR, "reference count overflow\n");
return -1;
}
if(reordering_of_pic_nums_idc<3){
+ int bot;
if(reordering_of_pic_nums_idc<2){
const unsigned int abs_diff_pic_num= get_ue_golomb(&s->gb) + 1;
+ int frame_num;
if(abs_diff_pic_num >= h->max_pic_num){
av_log(h->s.avctx, AV_LOG_ERROR, "abs_diff_pic_num overflow\n");
return -1;
}
if(reordering_of_pic_nums_idc == 0) pred-= abs_diff_pic_num;
else pred+= abs_diff_pic_num;
pred &= h->max_pic_num - 1;
+ if (FIELD_PICTURE) {
+ frame_num = pred >> 1;
+ if (pred & 1) {
+ pic_structure = s->picture_structure;
+ bot = (s->picture_structure == PICT_BOTTOM_FIELD);
+ } else {
+ pic_structure = PICT_FRAME - s->picture_structure;
+ bot = (s->picture_structure == PICT_TOP_FIELD);
+ }
+ } else {
+ frame_num = pred;
+ pic_structure = PICT_FRAME;
+ bot = 0;
+ }
+
for(i= h->short_ref_count-1; i>=0; i--){
ref = h->short_ref[i];
- assert(ref->reference == 3);
+ assert(ref->reference);
assert(!ref->long_ref);
- if(ref->data[0] != NULL && ref->frame_num == pred && ref->long_ref == 0) // ignore non existing pictures by testing data[0] pointer
+ if(ref->data[0] != NULL &&
+ ref->frame_num == frame_num &&
+ (ref->reference & pic_structure) &&
+ ref->long_ref == 0) // ignore non existing pictures by testing data[0] pointer
break;
}
if(i>=0)
- ref->pic_id= ref->frame_num;
+ ref->pic_id= pred;
}else{
+ int long_idx;
pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx
- if(pic_id>31){
+
+ if (FIELD_PICTURE) {
+ long_idx = pic_id >> 1;
+ if (pic_id & 1) {
+ pic_structure = s->picture_structure;
+ bot = (s->picture_structure == PICT_BOTTOM_FIELD);
+ } else {
+ pic_structure = PICT_FRAME - s->picture_structure;
+ bot = (s->picture_structure == PICT_TOP_FIELD);
+ }
+ } else {
+ long_idx = pic_id;
+ pic_structure = PICT_FRAME;
+ bot = 0;
+ }
+
+ if(long_idx>31){
av_log(h->s.avctx, AV_LOG_ERROR, "long_term_pic_idx overflow\n");
return -1;
}
- ref = h->long_ref[pic_id];
- if(ref){
+ ref = h->long_ref[long_idx];
+ assert(!(ref && !ref->reference));
+ if(ref && (ref->reference & pic_structure)){
ref->pic_id= pic_id;
- assert(ref->reference == 3);
assert(ref->long_ref);
i=0;
}else{
i=-1;
}
@@ -2953,10 +3131,12 @@
}
for(; i > index; i--){
h->ref_list[list][i]= h->ref_list[list][i-1];
}
h->ref_list[list][index]= *ref;
+ if (FIELD_PICTURE)
+ pic_as_field(&h->ref_list[list][index], bot);
}
}else{
av_log(h->s.avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n");
return -1;
}
@@ -3091,40 +3271,55 @@
h->implicit_weight[ref0][ref1] = 32;
}
}
}
-static inline void unreference_pic(H264Context *h, Picture *pic){
+/**
+ * Mark a picture as no longer needed for reference. The refmask
+ * argument allows unreferencing of individual fields or the whole frame.
+ * If the picture becomes entirely unreferenced, but is being held for
+ * display purposes, it is marked as such.
+ * @param refmask mask of fields to unreference; the mask is bitwise
+ * anded with the reference marking of pic
+ * @return non-zero if pic becomes entirely unreferenced (except possibly
+ * for display purposes) zero if one of the fields remains in
+ * reference
+ */
+static inline int unreference_pic(H264Context *h, Picture *pic, int refmask){
int i;
- pic->reference=0;
+ if (pic->reference &= refmask) {
+ return 0;
+ } else {
if(pic == h->delayed_output_pic)
pic->reference=DELAYED_PIC_REF;
else{
for(i = 0; h->delayed_pic[i]; i++)
if(pic == h->delayed_pic[i]){
pic->reference=DELAYED_PIC_REF;
break;
}
}
+ return 1;
+ }
}
/**
* instantaneous decoder refresh.
*/
static void idr(H264Context *h){
int i;
for(i=0; i<16; i++){
if (h->long_ref[i] != NULL) {
- unreference_pic(h, h->long_ref[i]);
+ unreference_pic(h, h->long_ref[i], 0);
h->long_ref[i]= NULL;
}
}
h->long_ref_count=0;
for(i=0; i<h->short_ref_count; i++){
- unreference_pic(h, h->short_ref[i]);
+ unreference_pic(h, h->short_ref[i], 0);
h->short_ref[i]= NULL;
}
h->short_ref_count=0;
}
@@ -3141,47 +3336,90 @@
h->delayed_output_pic->reference= 0;
h->delayed_output_pic= NULL;
idr(h);
if(h->s.current_picture_ptr)
h->s.current_picture_ptr->reference= 0;
+ h->s.first_field= 0;
}
/**
- *
- * @return the removed picture or NULL if an error occurs
+ * Find a Picture in the short term reference list by frame number.
+ * @param frame_num frame number to search for
+ * @param idx the index into h->short_ref where returned picture is found
+ * undefined if no picture found.
+ * @return pointer to the found picture, or NULL if no pic with the provided
+ * frame number is found
*/
-static Picture * remove_short(H264Context *h, int frame_num){
+static Picture * find_short(H264Context *h, int frame_num, int *idx){
MpegEncContext * const s = &h->s;
int i;
- if(s->avctx->debug&FF_DEBUG_MMCO)
- av_log(h->s.avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count);
-
for(i=0; i<h->short_ref_count; i++){
Picture *pic= h->short_ref[i];
if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "%d %d %p\n", i, pic->frame_num, pic);
- if(pic->frame_num == frame_num){
- h->short_ref[i]= NULL;
- if (--h->short_ref_count)
- memmove(&h->short_ref[i], &h->short_ref[i+1], (h->short_ref_count - i)*sizeof(Picture*));
+ if(pic->frame_num == frame_num) {
+ *idx = i;
return pic;
}
}
return NULL;
}
/**
+ * Remove a picture from the short term reference list by its index in
+ * that list. This does no checking on the provided index; it is assumed
+ * to be valid. Other list entries are shifted down.
+ * @param i index into h->short_ref of picture to remove.
+ */
+static void remove_short_at_index(H264Context *h, int i){
+ assert(i > 0 && i < h->short_ref_count);
+ h->short_ref[i]= NULL;
+ if (--h->short_ref_count)
+ memmove(&h->short_ref[i], &h->short_ref[i+1], (h->short_ref_count - i)*sizeof(Picture*));
+}
+
+/**
+ *
+ * @return the removed picture or NULL if an error occurs
+ */
+static Picture * remove_short(H264Context *h, int frame_num){
+ MpegEncContext * const s = &h->s;
+ Picture *pic;
+ int i;
+
+ if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count);
+
+ pic = find_short(h, frame_num, &i);
+ if (pic)
+ remove_short_at_index(h, i);
+
+ return pic;
+}
+
+/**
+ * Remove a picture from the long term reference list by its index in
+ * that list. This does no checking on the provided index; it is assumed
+ * to be valid. The removed entry is set to NULL. Other entries are unaffected.
+ * @param i index into h->long_ref of picture to remove.
+ */
+static void remove_long_at_index(H264Context *h, int i){
+ h->long_ref[i]= NULL;
+ h->long_ref_count--;
+}
+
+/**
*
* @return the removed picture or NULL if an error occurs
*/
static Picture * remove_long(H264Context *h, int i){
Picture *pic;
pic= h->long_ref[i];
- h->long_ref[i]= NULL;
- if(pic) h->long_ref_count--;
+ if (pic)
+ remove_long_at_index(h, i);
return pic;
}
/**
@@ -3218,11 +3456,11 @@
* Executes the reference picture marking (memory management control operations).
*/
static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
MpegEncContext * const s = &h->s;
int i, j;
- int current_is_long=0;
+ int current_ref_assigned=0;
Picture *pic;
if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0)
av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n");
@@ -3230,78 +3468,148 @@
if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, h->mmco[i].short_pic_num, h->mmco[i].long_arg);
switch(mmco[i].opcode){
case MMCO_SHORT2UNUSED:
- pic= remove_short(h, mmco[i].short_pic_num);
- if(pic)
- unreference_pic(h, pic);
- else if(s->avctx->debug&FF_DEBUG_MMCO)
- av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_short() failure\n");
+ if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n", h->mmco[i].short_pic_num, h->short_ref_count);
+ pic = find_short(h, mmco[i].short_pic_num >> FIELD_PICTURE, &j);
+ if (pic) {
+ int mask = (!FIELD_PICTURE || mmco[i].short_pic_num & 1) ?
+ ~s->picture_structure : s->picture_structure;
+ if (unreference_pic(h, pic, mask))
+ remove_short_at_index(h, j);
+ } else if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short failure\n");
break;
case MMCO_SHORT2LONG:
- pic= remove_long(h, mmco[i].long_arg);
- if(pic) unreference_pic(h, pic);
+ if (FIELD_PICTURE && mmco[i].long_arg < h->long_ref_count &&
+ h->long_ref[mmco[i].long_arg]->frame_num ==
+ mmco[i].short_pic_num / 2) {
+ /* do nothing, we've already moved this field pair. */
+ } else {
+ int frame_num = mmco[i].short_pic_num >> FIELD_PICTURE;
- h->long_ref[ mmco[i].long_arg ]= remove_short(h, mmco[i].short_pic_num);
+ pic= remove_long(h, mmco[i].long_arg);
+ if(pic) unreference_pic(h, pic, 0);
+
+ h->long_ref[ mmco[i].long_arg ]= remove_short(h, frame_num);
if (h->long_ref[ mmco[i].long_arg ]){
h->long_ref[ mmco[i].long_arg ]->long_ref=1;
h->long_ref_count++;
}
+ }
break;
case MMCO_LONG2UNUSED:
- pic= remove_long(h, mmco[i].long_arg);
- if(pic)
- unreference_pic(h, pic);
- else if(s->avctx->debug&FF_DEBUG_MMCO)
- av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_long() failure\n");
+ j = mmco[i].long_arg >> FIELD_PICTURE;
+ pic = h->long_ref[j];
+ if (pic) {
+ int mask = (!FIELD_PICTURE || mmco[i].long_arg & 1) ?
+ ~s->picture_structure : s->picture_structure;
+ if (unreference_pic(h, pic, mask))
+ remove_long_at_index(h, j);
+ } else if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref long failure\n");
break;
case MMCO_LONG:
+ j = 1;
+ if (FIELD_PICTURE && !s->first_field) {
+ if (h->long_ref[mmco[i].long_arg] == s->current_picture_ptr) {
+ /* Just mark second field as referenced */
+ j = 0;
+ } else if (s->current_picture_ptr->reference) {
+ /* First field in pair is in short term list or
+ * at a different long term index.
+ * This is not allowed; see 7.4.3, notes 2 and 3.
+ * Report the problem and keep the pair where it is,
+ * and mark this field valid.
+ */
+ av_log(h->s.avctx, AV_LOG_ERROR,
+ "illegal long term reference assignment for second "
+ "field in complementary field pair (first field is "
+ "short term or has non-matching long index)\n");
+ j = 0;
+ }
+ }
+
+ if (j) {
pic= remove_long(h, mmco[i].long_arg);
- if(pic) unreference_pic(h, pic);
+ if(pic) unreference_pic(h, pic, 0);
h->long_ref[ mmco[i].long_arg ]= s->current_picture_ptr;
h->long_ref[ mmco[i].long_arg ]->long_ref=1;
h->long_ref_count++;
+ }
- current_is_long=1;
+ s->current_picture_ptr->reference |= s->picture_structure;
+ current_ref_assigned=1;
break;
case MMCO_SET_MAX_LONG:
assert(mmco[i].long_arg <= 16);
// just remove the long term which index is greater than new max
for(j = mmco[i].long_arg; j<16; j++){
pic = remove_long(h, j);
- if (pic) unreference_pic(h, pic);
+ if (pic) unreference_pic(h, pic, 0);
}
break;
case MMCO_RESET:
while(h->short_ref_count){
pic= remove_short(h, h->short_ref[0]->frame_num);
- if(pic) unreference_pic(h, pic);
+ if(pic) unreference_pic(h, pic, 0);
}
for(j = 0; j < 16; j++) {
pic= remove_long(h, j);
- if(pic) unreference_pic(h, pic);
+ if(pic) unreference_pic(h, pic, 0);
}
break;
default: assert(0);
}
}
- if(!current_is_long){
+ if (!current_ref_assigned && FIELD_PICTURE &&
+ !s->first_field && s->current_picture_ptr->reference) {
+
+ /* Second field of complementary field pair; the first field of
+ * which is already referenced. If short referenced, it
+ * should be first entry in short_ref. If not, it must exist
+ * in long_ref; trying to put it on the short list here is an
+ * error in the encoded bit stream (ref: 7.4.3, NOTE 2 and 3).
+ * If on neither list, we have a problem elsewhere
+ */
+ if (h->short_ref_count && h->short_ref[0] == s->current_picture_ptr) {
+ /* Just mark the second field valid */
+ s->current_picture_ptr->reference = PICT_FRAME;
+ } else if (s->current_picture_ptr->long_ref) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term reference "
+ "assignment for second field "
+ "in complementary field pair "
+ "(first field is long term)\n");
+ } else {
+ av_log(h->s.avctx, AV_LOG_ERROR, "problem in internal reference "
+ "list handling; marking second "
+ "field in pair finds first field "
+ "in reference, but not in any "
+ "ref list\n");
+ s->current_picture_ptr->reference = 0;
+ }
+ current_ref_assigned = 1;
+ }
+
+ if(!current_ref_assigned){
pic= remove_short(h, s->current_picture_ptr->frame_num);
if(pic){
- unreference_pic(h, pic);
+ unreference_pic(h, pic, 0);
av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n");
}
if(h->short_ref_count)
memmove(&h->short_ref[1], &h->short_ref[0], h->short_ref_count*sizeof(Picture*));
h->short_ref[0]= s->current_picture_ptr;
h->short_ref[0]->long_ref=0;
h->short_ref_count++;
+ s->current_picture_ptr->reference |= s->picture_structure;
}
print_short_term(h);
print_long_term(h);
return 0;
@@ -3325,23 +3633,23 @@
for(i= 0; i<MAX_MMCO_COUNT; i++) {
MMCOOpcode opcode= get_ue_golomb(gb);
h->mmco[i].opcode= opcode;
if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){
- h->mmco[i].short_pic_num= (h->frame_num - get_ue_golomb(gb) - 1) & ((1<<h->sps.log2_max_frame_num)-1); //FIXME fields
+ h->mmco[i].short_pic_num= (h->curr_pic_num - get_ue_golomb(gb) - 1) & (h->max_pic_num - 1);
/* if(h->mmco[i].short_pic_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_pic_num ] == NULL){
av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco);
return -1;
}*/
}
if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){
- unsigned int long_index= get_ue_golomb(gb);
- if(/*h->mmco[i].long_arg >= h->long_ref_count || h->long_ref[ h->mmco[i].long_arg ] == NULL*/ long_index >= 16){
+ unsigned int long_arg= get_ue_golomb(gb);
+ if(long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE))){
av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode);
return -1;
}
- h->mmco[i].long_arg= long_index;
+ h->mmco[i].long_arg= long_arg;
}
if(opcode > (unsigned)MMCO_LONG){
av_log(h->s.avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode);
return -1;
@@ -3351,14 +3659,21 @@
}
h->mmco_index= i;
}else{
assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);
- if(h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count){ //FIXME fields
+ if(h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count &&
+ !(FIELD_PICTURE && !s->first_field && s->current_picture_ptr->reference)) {
h->mmco[0].opcode= MMCO_SHORT2UNUSED;
h->mmco[0].short_pic_num= h->short_ref[ h->short_ref_count - 1 ]->frame_num;
h->mmco_index= 1;
+ if (FIELD_PICTURE) {
+ h->mmco[0].short_pic_num *= 2;
+ h->mmco[1].opcode= MMCO_SHORT2UNUSED;
+ h->mmco[1].short_pic_num= h->mmco[0].short_pic_num + 1;
+ h->mmco_index= 2;
+ }
}else
h->mmco_index= 0;
}
}
@@ -3442,15 +3757,19 @@
}
field_poc[0]= poc;
field_poc[1]= poc;
}
- if(s->picture_structure != PICT_BOTTOM_FIELD)
+ if(s->picture_structure != PICT_BOTTOM_FIELD) {
s->current_picture_ptr->field_poc[0]= field_poc[0];
- if(s->picture_structure != PICT_TOP_FIELD)
+ s->current_picture_ptr->poc = field_poc[0];
+ }
+ if(s->picture_structure != PICT_TOP_FIELD) {
s->current_picture_ptr->field_poc[1]= field_poc[1];
- if(s->picture_structure == PICT_FRAME) // FIXME field pix?
+ s->current_picture_ptr->poc = field_poc[1];
+ }
+ if(!FIELD_PICTURE || !s->first_field)
s->current_picture_ptr->poc= FFMIN(field_poc[0], field_poc[1]);
return 0;
}
@@ -3512,10 +3831,11 @@
memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset));
dst->s.current_picture_ptr = src->s.current_picture_ptr;
dst->s.current_picture = src->s.current_picture;
dst->s.linesize = src->s.linesize;
dst->s.uvlinesize = src->s.uvlinesize;
+ dst->s.first_field = src->s.first_field;
dst->prev_poc_msb = src->prev_poc_msb;
dst->prev_poc_lsb = src->prev_poc_lsb;
dst->prev_frame_num_offset = src->prev_frame_num_offset;
dst->prev_frame_num = src->prev_frame_num;
@@ -3539,24 +3859,27 @@
*
* @return 0 if okay, <0 if an error occured, 1 if decoding must not be multithreaded
*/
static int decode_slice_header(H264Context *h, H264Context *h0){
MpegEncContext * const s = &h->s;
+ MpegEncContext * const s0 = &h0->s;
unsigned int first_mb_in_slice;
unsigned int pps_id;
int num_ref_idx_active_override_flag;
static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
unsigned int slice_type, tmp, i;
int default_ref_list_done = 0;
+ int last_pic_structure;
s->dropable= h->nal_ref_idc == 0;
first_mb_in_slice= get_ue_golomb(&s->gb);
if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){
h0->current_slice = 0;
- s->current_picture_ptr= NULL;
+ if (!s0->first_field)
+ s->current_picture_ptr= NULL;
}
slice_type= get_ue_golomb(&s->gb);
if(slice_type > 9){
av_log(h->s.avctx, AV_LOG_ERROR, "slice type too large (%d) at %d %d\n", h->slice_type, s->mb_x, s->mb_y);
@@ -3621,10 +3944,11 @@
if (!s->context_initialized) {
if(h != h0)
return -1; // we cant (re-)initialize context during parallel decoding
if (MPV_common_init(s) < 0)
return -1;
+ s->first_field = 0;
init_scan_tables(h);
alloc_tables(h);
for(i = 1; i < s->avctx->thread_count; i++) {
@@ -3659,26 +3983,69 @@
h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num);
h->mb_mbaff = 0;
h->mb_aff_frame = 0;
+ last_pic_structure = s0->picture_structure;
if(h->sps.frame_mbs_only_flag){
s->picture_structure= PICT_FRAME;
}else{
if(get_bits1(&s->gb)) { //field_pic_flag
s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag
- av_log(h->s.avctx, AV_LOG_ERROR, "PAFF interlacing is not implemented\n");
} else {
s->picture_structure= PICT_FRAME;
h->mb_aff_frame = h->sps.mb_aff;
}
}
if(h0->current_slice == 0){
- if(frame_start(h) < 0)
+ /* See if we have a decoded first field looking for a pair... */
+ if (s0->first_field) {
+ assert(s0->current_picture_ptr);
+ assert(s0->current_picture_ptr->data[0]);
+ assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF);
+
+ /* figure out if we have a complementary field pair */
+ if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) {
+ /*
+ * Previous field is unmatched. Don't display it, but let it
+ * remain for reference if marked as such.
+ */
+ s0->current_picture_ptr = NULL;
+ s0->first_field = FIELD_PICTURE;
+
+ } else {
+ if (h->nal_ref_idc &&
+ s0->current_picture_ptr->reference &&
+ s0->current_picture_ptr->frame_num != h->frame_num) {
+ /*
+ * This and previous field were reference, but had
+ * different frame_nums. Consider this field first in
+ * pair. Throw away previous field except for reference
+ * purposes.
+ */
+ s0->first_field = 1;
+ s0->current_picture_ptr = NULL;
+
+ } else {
+ /* Second field in complementary pair */
+ s0->first_field = 0;
+ }
+ }
+
+ } else {
+ /* Frame or first field in a potentially complementary pair */
+ assert(!s0->current_picture_ptr);
+ s0->first_field = FIELD_PICTURE;
+ }
+
+ if((!FIELD_PICTURE || s0->first_field) && frame_start(h) < 0) {
+ s0->first_field = 0;
return -1;
+ }
}
+
if(h != h0)
clone_slice(h, h0);
s->current_picture_ptr->frame_num= h->frame_num; //FIXME frame_num cleanup
@@ -3688,17 +4055,22 @@
av_log(h->s.avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n");
return -1;
}
s->resync_mb_x = s->mb_x = first_mb_in_slice % s->mb_width;
s->resync_mb_y = s->mb_y = (first_mb_in_slice / s->mb_width) << h->mb_aff_frame;
+ if (FIELD_PICTURE) {
+ s->resync_mb_y = s->mb_y = s->mb_y * 2;
+ if (s->picture_structure == PICT_BOTTOM_FIELD)
+ s->resync_mb_y = s->mb_y = s->mb_y + 1;
+ }
assert(s->mb_y < s->mb_height);
if(s->picture_structure==PICT_FRAME){
h->curr_pic_num= h->frame_num;
h->max_pic_num= 1<< h->sps.log2_max_frame_num;
}else{
- h->curr_pic_num= 2*h->frame_num;
+ h->curr_pic_num= 2*h->frame_num + 1;
h->max_pic_num= 1<<(h->sps.log2_max_frame_num + 1);
}
if(h->nal_unit_type == NAL_IDR_SLICE){
get_ue_golomb(&s->gb); /* idr_pic_id */
@@ -3730,11 +4102,11 @@
h->ref_count[1]= h->pps.ref_count[1];
if(h->slice_type == P_TYPE || h->slice_type == SP_TYPE || h->slice_type == B_TYPE){
if(h->slice_type == B_TYPE){
h->direct_spatial_mv_pred= get_bits1(&s->gb);
- if(h->sps.mb_aff && h->direct_spatial_mv_pred)
+ if(h->mb_aff_frame && h->direct_spatial_mv_pred)
av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF + spatial direct mode is not implemented\n");
}
num_ref_idx_active_override_flag= get_bits1(&s->gb);
if(num_ref_idx_active_override_flag){
@@ -3850,11 +4222,11 @@
h0->last_slice_type = slice_type;
h->slice_num = ++h0->current_slice;
h->emu_edge_width= (s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16;
- h->emu_edge_height= FRAME_MBAFF ? 0 : h->emu_edge_width;
+ h->emu_edge_height= (FRAME_MBAFF || FIELD_PICTURE) ? 0 : h->emu_edge_width;
if(s->avctx->debug&FF_DEBUG_PICT_INFO){
av_log(h->s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s\n",
h->slice_num,
(s->picture_structure==PICT_FRAME ? "F" : s->picture_structure==PICT_TOP_FIELD ? "T" : "B"),
@@ -4748,10 +5120,12 @@
mbb_xy = mb_x + (mb_y-1)*s->mb_stride;
}else{
int mb_xy = mb_x + mb_y*s->mb_stride;
mba_xy = mb_xy - 1;
mbb_xy = mb_xy - s->mb_stride;
+ if (FIELD_PICTURE)
+ mbb_xy -= s->mb_stride;
}
if( h->slice_table[mba_xy] == h->slice_num && !IS_SKIP( s->current_picture.mb_type[mba_xy] ))
ctx++;
if( h->slice_table[mbb_xy] == h->slice_num && !IS_SKIP( s->current_picture.mb_type[mbb_xy] ))
@@ -5198,10 +5566,12 @@
h->top_mb_xy -= s->mb_stride;
}
if (left_mb_frame_flag != curr_mb_frame_flag) {
h->left_mb_xy[0] = pair_xy - 1;
}
+ } else if (FIELD_PICTURE) {
+ h->top_mb_xy -= s->mb_stride;
}
return;
}
/**
@@ -6433,11 +6803,11 @@
if( ++s->mb_x >= s->mb_width ) {
s->mb_x = 0;
ff_draw_horiz_band(s, 16*s->mb_y, 16);
++s->mb_y;
- if(FRAME_MBAFF) {
+ if(FRAME_MBAFF || FIELD_PICTURE) {
++s->mb_y;
}
}
if( eos || s->mb_y >= s->mb_height ) {
@@ -6470,11 +6840,11 @@
if(++s->mb_x >= s->mb_width){
s->mb_x=0;
ff_draw_horiz_band(s, 16*s->mb_y, 16);
++s->mb_y;
- if(FRAME_MBAFF) {
+ if(FRAME_MBAFF || FIELD_PICTURE) {
++s->mb_y;
}
if(s->mb_y >= s->mb_height){
tprintf(s->avctx, "slice end %d %d\n", get_bits_count(&s->gb), s->gb.size_in_bits);
@@ -7047,10 +7417,12 @@
/* pull back stuff from slices to master context */
hx = h->thread_context[context_count - 1];
s->mb_x = hx->s.mb_x;
s->mb_y = hx->s.mb_y;
+ s->dropable = hx->s.dropable;
+ s->picture_structure = hx->s.picture_structure;
for(i = 1; i < context_count; i++)
h->s.error_count += h->thread_context[i]->s.error_count;
}
}
@@ -7069,11 +7441,12 @@
av_log(NULL, AV_LOG_ERROR,"%02X ", buf[i]);
}
#endif
if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
h->current_slice = 0;
- s->current_picture_ptr= NULL;
+ if (!s->first_field)
+ s->current_picture_ptr= NULL;
}
for(;;){
int consumed;
int dst_length;
@@ -7148,11 +7521,11 @@
hx->s.data_partitioning = 0;
if((err = decode_slice_header(hx, h)))
break;
- s->current_picture_ptr->key_frame= (hx->nal_unit_type == NAL_IDR_SLICE);
+ s->current_picture_ptr->key_frame|= (hx->nal_unit_type == NAL_IDR_SLICE);
if(hx->redundant_pic_count==0 && hx->s.hurry_up < 5
&& (avctx->skip_frame < AVDISCARD_NONREF || hx->nal_ref_idc)
&& (avctx->skip_frame < AVDISCARD_BIDIR || hx->slice_type!=B_TYPE)
&& (avctx->skip_frame < AVDISCARD_NONKEY || hx->slice_type==I_TYPE)
&& avctx->skip_frame < AVDISCARD_ALL)
@@ -7366,21 +7739,39 @@
s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
s->current_picture_ptr->pict_type= s->pict_type;
h->prev_frame_num_offset= h->frame_num_offset;
h->prev_frame_num= h->frame_num;
- if(s->current_picture_ptr->reference & s->picture_structure){
+ if(!s->dropable) {
h->prev_poc_msb= h->poc_msb;
h->prev_poc_lsb= h->poc_lsb;
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
}
- ff_er_frame_end(s);
+ /*
+ * FIXME: Error handling code does not seem to support interlaced
+ * when slices span multiple rows
+ * The ff_er_add_slice calls don't work right for bottom
+ * fields; they cause massive erroneous error concealing
+ * Error marking covers both fields (top and bottom).
+ * This causes a mismatched s->error_count
+ * and a bad error table. Further, the error count goes to
+ * INT_MAX when called for bottom field, because mb_y is
+ * past end by one (callers fault) and resync_mb_y != 0
+ * causes problems for the first MB line, too.
+ */
+ if (!FIELD_PICTURE)
+ ff_er_frame_end(s);
MPV_frame_end(s);
- //FIXME do something with unavailable reference frames
+ if (s->first_field) {
+ /* Wait for second field. */
+ *data_size = 0;
+
+ } else {
+ //FIXME do something with unavailable reference frames
#if 0 //decode order
*data_size = sizeof(AVFrame);
#else
/* Sort B-frames into display order */
@@ -7446,10 +7837,11 @@
if(out)
*pict= *(AVFrame*)out;
else
av_log(avctx, AV_LOG_DEBUG, "no picture\n");
+ }
}
assert(pict->data[0] || !*data_size);
ff_print_debug_info(s, pict);
//printf("out %d\n", (int)pict->data[0]);
--- ../ffmpeg-cosmetics/libavcodec/h264.h 2007-09-24 17:07:39.000000000 -0400
+++ libavcodec/h264.h 2007-09-24 17:08:08.000000000 -0400
@@ -57,14 +57,16 @@
#ifdef ALLOW_INTERLACE
#define MB_MBAFF h->mb_mbaff
#define MB_FIELD h->mb_field_decoding_flag
#define FRAME_MBAFF h->mb_aff_frame
+#define FIELD_PICTURE (s->picture_structure != PICT_FRAME)
#else
#define MB_MBAFF 0
#define MB_FIELD 0
#define FRAME_MBAFF 0
+#define FIELD_PICTURE 0
#undef IS_INTERLACED
#define IS_INTERLACED(mb_type) 0
#endif
/**
@@ -281,11 +283,11 @@
int frame_num_offset; ///< for POC type 2
int prev_frame_num_offset; ///< for POC type 2
int prev_frame_num; ///< frame_num of the last pic for POC type 1/2
/**
- * frame_num for frames or 2*frame_num for field pics.
+ * frame_num for frames or 2*frame_num+1 for field pics.
*/
int curr_pic_num;
/**
* max_frame_num or 2*max_frame_num for field pics.
--- ../ffmpeg-cosmetics/libavcodec/mpegvideo.c 2007-09-26 15:22:59.000000000 -0400
+++ libavcodec/mpegvideo.c 2007-10-01 15:25:45.000000000 -0400
@@ -952,11 +952,11 @@
goto alloc;
}
assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0]));
- if(s->picture_structure!=PICT_FRAME){
+ if(s->picture_structure!=PICT_FRAME && s->out_format != FMT_H264){
int i;
for(i=0; i<4; i++){
if(s->picture_structure == PICT_BOTTOM_FIELD){
s->current_picture.data[i] += s->current_picture.linesize[i];
}
More information about the ffmpeg-devel
mailing list