Mercurial > libavcodec.hg
comparison h264.c @ 7398:bcede7e06618 libavcodec
Rewrite fill_default_ref_list(), the old code was obfuscated beyond
repair with hacks.
new code is ~60lines old was ~200
Fixes at least:
FRExt/HCHP2_HHI_A.264
one sample also get decoded much better:
FRExt/FRExt1_Panasonic.avc (PSNR 11 -> 80)
(no i do not know why, the old code was too a big mess to figure out
what it did)
author | michael |
---|---|
date | Fri, 25 Jul 2008 21:46:15 +0000 |
parents | 535664ced6f0 |
children | fa2d6f49e3ae |
comparison
equal
deleted
inserted
replaced
7397:535664ced6f0 | 7398:bcede7e06618 |
---|---|
2768 int parity, int id_add){ | 2768 int parity, int id_add){ |
2769 int match = !!(src->reference & parity); | 2769 int match = !!(src->reference & parity); |
2770 | 2770 |
2771 if (match) { | 2771 if (match) { |
2772 *dest = *src; | 2772 *dest = *src; |
2773 if(parity != PICT_FRAME){ | |
2773 pic_as_field(dest, parity); | 2774 pic_as_field(dest, parity); |
2774 dest->pic_id *= 2; | 2775 dest->pic_id *= 2; |
2775 dest->pic_id += id_add; | 2776 dest->pic_id += id_add; |
2777 } | |
2776 } | 2778 } |
2777 | 2779 |
2778 return match; | 2780 return match; |
2779 } | 2781 } |
2780 | 2782 |
2781 /** | 2783 static int build_def_list(Picture *def, Picture **in, int len, int is_long, int sel){ |
2782 * Split one reference list into field parts, interleaving by parity | 2784 int i[2]={0}; |
2783 * as per H.264 spec section 8.2.4.2.5. Output fields have their data pointers | 2785 int index=0; |
2784 * set to look at the actual start of data for that field. | 2786 |
2785 * | 2787 while(i[0]<len || i[1]<len){ |
2786 * @param dest output list | 2788 while(i[0]<len && !(in[ i[0] ] && (in[ i[0] ]->reference & sel))) |
2787 * @param dest_len maximum number of fields to put in dest | 2789 i[0]++; |
2788 * @param src the source reference list containing fields and/or field pairs | 2790 while(i[1]<len && !(in[ i[1] ] && (in[ i[1] ]->reference & (sel^3)))) |
2789 * (aka short_ref/long_ref, or | 2791 i[1]++; |
2790 * refFrameListXShortTerm/refFrameListLongTerm in spec-speak) | 2792 if(i[0] < len){ |
2791 * @param src_len number of Picture's in source (pairs and unmatched fields) | 2793 in[ i[0] ]->pic_id= is_long ? i[0] : in[ i[0] ]->frame_num; |
2792 * @param parity the parity of the picture being decoded/needing | 2794 split_field_copy(&def[index++], in[ i[0]++ ], sel , 1); |
2793 * these ref pics (PICT_{TOP,BOTTOM}_FIELD) | 2795 } |
2794 * @return number of fields placed in dest | 2796 if(i[1] < len){ |
2795 */ | 2797 in[ i[1] ]->pic_id= is_long ? i[1] : in[ i[1] ]->frame_num; |
2796 static int split_field_half_ref_list(Picture *dest, int dest_len, | 2798 split_field_copy(&def[index++], in[ i[1]++ ], sel^3, 0); |
2797 Picture *src, int src_len, int parity){ | 2799 } |
2798 int same_parity = 1; | 2800 } |
2799 int same_i = 0; | 2801 |
2800 int opp_i = 0; | 2802 return index; |
2801 int out_i; | 2803 } |
2802 int field_output; | 2804 |
2803 | 2805 static int add_sorted(Picture **sorted, Picture **src, int len, int limit, int dir){ |
2804 for (out_i = 0; out_i < dest_len; out_i += field_output) { | 2806 int i, best_poc; |
2805 if (same_parity && same_i < src_len) { | 2807 int out_i= 0; |
2806 field_output = split_field_copy(dest + out_i, src + same_i, | 2808 |
2807 parity, 1); | 2809 for(;;){ |
2808 same_parity = !field_output; | 2810 best_poc= dir ? INT_MIN : INT_MAX; |
2809 same_i++; | 2811 |
2810 | 2812 for(i=0; i<len; i++){ |
2811 } else if (opp_i < src_len) { | 2813 const int poc= src[i]->poc; |
2812 field_output = split_field_copy(dest + out_i, src + opp_i, | 2814 if(((poc > limit) ^ dir) && ((poc < best_poc) ^ dir)){ |
2813 PICT_FRAME - parity, 0); | 2815 best_poc= poc; |
2814 same_parity = field_output; | 2816 sorted[out_i]= src[i]; |
2815 opp_i++; | 2817 } |
2816 | 2818 } |
2817 } else { | 2819 if(best_poc == (dir ? INT_MIN : INT_MAX)) |
2818 break; | 2820 break; |
2819 } | 2821 limit= sorted[out_i++]->poc - dir; |
2820 } | 2822 } |
2821 | |
2822 return out_i; | 2823 return out_i; |
2823 } | |
2824 | |
2825 /** | |
2826 * Split the reference frame list into a reference field list. | |
2827 * This implements H.264 spec 8.2.4.2.5 for a combined input list. | |
2828 * The input list contains both reference field pairs and | |
2829 * unmatched reference fields; it is ordered as spec describes | |
2830 * RefPicListX for frames in 8.2.4.2.1 and 8.2.4.2.3, except that | |
2831 * unmatched field pairs are also present. Conceptually this is equivalent | |
2832 * to concatenation of refFrameListXShortTerm with refFrameListLongTerm. | |
2833 * | |
2834 * @param dest output reference list where ordered fields are to be placed | |
2835 * @param dest_len max number of fields to place at dest | |
2836 * @param src source reference list, as described above | |
2837 * @param src_len number of pictures (pairs and unmatched fields) in src | |
2838 * @param parity parity of field being currently decoded | |
2839 * (one of PICT_{TOP,BOTTOM}_FIELD) | |
2840 * @param long_i index into src array that holds first long reference picture, | |
2841 * or src_len if no long refs present. | |
2842 */ | |
2843 static int split_field_ref_list(Picture *dest, int dest_len, | |
2844 Picture *src, int src_len, | |
2845 int parity, int long_i){ | |
2846 | |
2847 int i = split_field_half_ref_list(dest, dest_len, src, long_i, parity); | |
2848 dest += i; | |
2849 dest_len -= i; | |
2850 | |
2851 i += split_field_half_ref_list(dest, dest_len, src + long_i, | |
2852 src_len - long_i, parity); | |
2853 return i; | |
2854 } | 2824 } |
2855 | 2825 |
2856 /** | 2826 /** |
2857 * fills the default_ref_list. | 2827 * fills the default_ref_list. |
2858 */ | 2828 */ |
2859 static int fill_default_ref_list(H264Context *h){ | 2829 static int fill_default_ref_list(H264Context *h){ |
2860 MpegEncContext * const s = &h->s; | 2830 MpegEncContext * const s = &h->s; |
2861 int i; | 2831 int i, len; |
2862 int smallest_poc_greater_than_current = -1; | |
2863 int structure_sel; | |
2864 Picture sorted_short_ref[32]; | |
2865 Picture field_entry_list[2][32]; | |
2866 Picture *frame_list[2]; | |
2867 | |
2868 if (FIELD_PICTURE) { | |
2869 structure_sel = PICT_FRAME; | |
2870 frame_list[0] = field_entry_list[0]; | |
2871 frame_list[1] = field_entry_list[1]; | |
2872 } else { | |
2873 structure_sel = 0; | |
2874 frame_list[0] = h->default_ref_list[0]; | |
2875 frame_list[1] = h->default_ref_list[1]; | |
2876 } | |
2877 | 2832 |
2878 if(h->slice_type_nos==FF_B_TYPE){ | 2833 if(h->slice_type_nos==FF_B_TYPE){ |
2879 int list; | 2834 Picture *sorted[32]; |
2880 int len[2]; | 2835 int cur_poc, list; |
2881 int short_len[2]; | 2836 int lens[2]; |
2882 int out_i; | 2837 |
2883 int limit= INT_MIN; | 2838 if(FIELD_PICTURE) |
2884 | 2839 cur_poc= s->current_picture_ptr->field_poc[ s->picture_structure == PICT_BOTTOM_FIELD ]; |
2885 /* sort frame according to POC in B slice */ | 2840 else |
2886 for(out_i=0; out_i<h->short_ref_count; out_i++){ | 2841 cur_poc= s->current_picture_ptr->poc; |
2887 int best_i=INT_MIN; | 2842 |
2888 int best_poc=INT_MAX; | 2843 for(list= 0; list<2; list++){ |
2889 | 2844 len= add_sorted(sorted , h->short_ref, h->short_ref_count, cur_poc, 1^list); |
2890 for(i=0; i<h->short_ref_count; i++){ | 2845 len+=add_sorted(sorted+len, h->short_ref, h->short_ref_count, cur_poc, 0^list); |
2891 const int poc= h->short_ref[i]->poc; | 2846 assert(len<=32); |
2892 if(poc > limit && poc < best_poc){ | 2847 len= build_def_list(h->default_ref_list[list] , sorted , len, 0, s->picture_structure); |
2893 best_poc= poc; | 2848 len+=build_def_list(h->default_ref_list[list]+len, h->long_ref, 16 , 1, s->picture_structure); |
2894 best_i= i; | 2849 assert(len<=32); |
2895 } | 2850 |
2896 } | 2851 if(len < h->ref_count[list]) |
2897 | 2852 memset(&h->default_ref_list[list][len], 0, sizeof(Picture)*(h->ref_count[list] - len)); |
2898 assert(best_i != INT_MIN); | 2853 lens[list]= len; |
2899 | 2854 } |
2900 limit= best_poc; | 2855 |
2901 sorted_short_ref[out_i]= *h->short_ref[best_i]; | 2856 if(lens[0] == lens[1] && lens[1] > 1){ |
2902 tprintf(h->s.avctx, "sorted poc: %d->%d poc:%d fn:%d\n", best_i, out_i, sorted_short_ref[out_i].poc, sorted_short_ref[out_i].frame_num); | 2857 for(i=0; h->default_ref_list[0][i].data[0] == h->default_ref_list[1][i].data[0] && i<lens[0]; i++); |
2903 if (-1 == smallest_poc_greater_than_current) { | 2858 if(i == lens[0]) |
2904 if (h->short_ref[best_i]->poc >= s->current_picture_ptr->poc) { | 2859 FFSWAP(Picture, h->default_ref_list[1][0], h->default_ref_list[1][1]); |
2905 smallest_poc_greater_than_current = out_i; | 2860 } |
2906 } | |
2907 } | |
2908 } | |
2909 | |
2910 tprintf(h->s.avctx, "current poc: %d, smallest_poc_greater_than_current: %d\n", s->current_picture_ptr->poc, smallest_poc_greater_than_current); | |
2911 | |
2912 // find the largest POC | |
2913 for(list=0; list<2; list++){ | |
2914 int index = 0; | |
2915 int j= -99; | |
2916 int step= list ? -1 : 1; | |
2917 | |
2918 for(i=0; i<h->short_ref_count && index < h->ref_count[list]; i++, j+=step) { | |
2919 int sel; | |
2920 while(j<0 || j>= h->short_ref_count){ | |
2921 if(j != -99 && step == (list ? -1 : 1)) | |
2922 return -1; | |
2923 step = -step; | |
2924 j= smallest_poc_greater_than_current + (step>>1); | |
2925 } | |
2926 sel = sorted_short_ref[j].reference | structure_sel; | |
2927 if(sel != PICT_FRAME) continue; | |
2928 frame_list[list][index ]= sorted_short_ref[j]; | |
2929 frame_list[list][index++].pic_id= sorted_short_ref[j].frame_num; | |
2930 } | |
2931 short_len[list] = index; | |
2932 | |
2933 for(i = 0; i < 16 && index < h->ref_count[ list ]; i++){ | |
2934 int sel; | |
2935 if(h->long_ref[i] == NULL) continue; | |
2936 sel = h->long_ref[i]->reference | structure_sel; | |
2937 if(sel != PICT_FRAME) continue; | |
2938 | |
2939 frame_list[ list ][index ]= *h->long_ref[i]; | |
2940 frame_list[ list ][index++].pic_id= i; | |
2941 } | |
2942 len[list] = index; | |
2943 } | |
2944 | |
2945 for(list=0; list<2; list++){ | |
2946 if (FIELD_PICTURE) | |
2947 len[list] = split_field_ref_list(h->default_ref_list[list], | |
2948 h->ref_count[list], | |
2949 frame_list[list], | |
2950 len[list], | |
2951 s->picture_structure, | |
2952 short_len[list]); | |
2953 | |
2954 // swap the two first elements of L1 when L0 and L1 are identical | |
2955 if(list && len[0] > 1 && len[0] == len[1]) | |
2956 for(i=0; h->default_ref_list[0][i].data[0] == h->default_ref_list[1][i].data[0]; i++) | |
2957 if(i == len[0]){ | |
2958 FFSWAP(Picture, h->default_ref_list[1][0], h->default_ref_list[1][1]); | |
2959 break; | |
2960 } | |
2961 | |
2962 if(len[list] < h->ref_count[ list ]) | |
2963 memset(&h->default_ref_list[list][len[list]], 0, sizeof(Picture)*(h->ref_count[ list ] - len[list])); | |
2964 } | |
2965 | |
2966 | |
2967 }else{ | 2861 }else{ |
2968 int index=0; | 2862 len = build_def_list(h->default_ref_list[0] , h->short_ref, h->short_ref_count, 0, s->picture_structure); |
2969 int short_len; | 2863 len+= build_def_list(h->default_ref_list[0]+len, h-> long_ref, 16 , 1, s->picture_structure); |
2970 for(i=0; i<h->short_ref_count; i++){ | 2864 assert(len <= 32); |
2971 int sel; | 2865 if(len < h->ref_count[0]) |
2972 sel = h->short_ref[i]->reference | structure_sel; | 2866 memset(&h->default_ref_list[0][len], 0, sizeof(Picture)*(h->ref_count[0] - len)); |
2973 if(sel != PICT_FRAME) continue; | |
2974 frame_list[0][index ]= *h->short_ref[i]; | |
2975 frame_list[0][index++].pic_id= h->short_ref[i]->frame_num; | |
2976 } | |
2977 short_len = index; | |
2978 for(i = 0; i < 16; i++){ | |
2979 int sel; | |
2980 if(h->long_ref[i] == NULL) continue; | |
2981 sel = h->long_ref[i]->reference | structure_sel; | |
2982 if(sel != PICT_FRAME) continue; | |
2983 frame_list[0][index ]= *h->long_ref[i]; | |
2984 frame_list[0][index++].pic_id= i; | |
2985 } | |
2986 | |
2987 if (FIELD_PICTURE) | |
2988 index = split_field_ref_list(h->default_ref_list[0], | |
2989 h->ref_count[0], frame_list[0], | |
2990 index, s->picture_structure, | |
2991 short_len); | |
2992 | |
2993 if(index < h->ref_count[0]) | |
2994 memset(&h->default_ref_list[0][index], 0, sizeof(Picture)*(h->ref_count[0] - index)); | |
2995 } | 2867 } |
2996 #ifdef TRACE | 2868 #ifdef TRACE |
2997 for (i=0; i<h->ref_count[0]; i++) { | 2869 for (i=0; i<h->ref_count[0]; i++) { |
2998 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]); | 2870 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]); |
2999 } | 2871 } |