# HG changeset patch # User andoma # Date 1191591687 0 # Node ID c4984d69d37331258392d656fbafa37d160c1bc7 # Parent 95916a621536ed5a22a2e2f6300a1b59aaebd288 Support functions and changes to default reference list creation for PAFF. patch by Jeff Downs, heydowns a borg d com original thread: Subject: [FFmpeg-devel] [PATCH] Implement PAFF in H.264 Date: 18/09/07 20:30 diff -r 95916a621536 -r c4984d69d373 h264.c --- a/h264.c Thu Oct 04 22:41:21 2007 +0000 +++ b/h264.c Fri Oct 05 13:41:27 2007 +0000 @@ -2764,6 +2764,104 @@ 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); + + 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_parity = 1; + int same_i = 0; + int opp_i = 0; + int out_i; + int field_output; + + for (out_i = 0; out_i < dest_len; out_i += field_output) { + if (same_parity && same_i < src_len) { + field_output = split_field_copy(dest + out_i, src + same_i, + parity, 1); + same_parity = !field_output; + same_i++; + + } else if (opp_i < src_len) { + field_output = split_field_copy(dest + out_i, src + opp_i, + PICT_FRAME - parity, 0); + same_parity = field_output; + opp_i++; + + } else { + break; + } + } + + 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. */ @@ -2771,9 +2869,25 @@ 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 = PICT_FRAME; + frame_list[0] = field_entry_list[0]; + frame_list[1] = field_entry_list[1]; + } else { + structure_sel = 0; + frame_list[0] = h->default_ref_list[0]; + frame_list[1] = h->default_ref_list[1]; + } if(h->slice_type==B_TYPE){ + int list; + int len[2]; + int short_len[2]; int out_i; int limit= INT_MIN; @@ -2801,11 +2915,7 @@ } } } - } - - 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 @@ -2815,57 +2925,83 @@ int step= list ? -1 : 1; for(i=0; ishort_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; - - h->default_ref_list[ list ][index ]= *h->long_ref[i]; - h->default_ref_list[ list ][index++].pic_id= i;; + sel = h->long_ref[i]->reference | structure_sel; + if(sel != PICT_FRAME) continue; + + 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 (FIELD_PICTURE) + 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; ishort_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 (FIELD_PICTURE) + 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; iref_count[0]; i++) {