[FFmpeg-devel] [PATCH] H.264/AVCHD interlaced fixes

Ivan Schreter schreter
Fri Feb 13 12:32:56 CET 2009


Michael Niedermayer wrote:
> On Tue, Feb 10, 2009 at 09:36:35PM +0100, Ivan Schreter wrote:
>   
> [...]
>   
>> #6a is the parsing of additional information from H.264 picture to get key 
>> frame flag, recovery count, field picture flag and frame number out of the 
>> stream in parser for latter use in lavf. Currently, only key frame flag can 
>> be transported via picture type, so recovery count and field picture flag 
>> are not yet communicated. These will be needed, though, in implementation 
>> of correct timestamps (and/or frame combining).
>>
>> So please review #6a.
>>
>> Regards,
>>
>> Ivan
>>
>>
>>     
>
> [...]
>   
>> +        ptr= ff_h264_decode_nal(h, buf, &dst_length, &consumed, buf_end - buf);
>>     
>
> this effectively reads through the whole bitstream
> obviously this is not ok and unneeded
>   
??? Why that? Before, you criticized copying too much code instead of 
reusing existing functions. So how'd you do it, so that it also *works* 
correctly? The original patch from you I took for the base namely didn't 
work...

>
>   
>> +        if (ptr==NULL || dst_length < 0)
>> +            break;
>> +        while(ptr[dst_length - 1] == 0 && dst_length > 0)
>> +            dst_length--;
>> +        bit_length= !dst_length ? 0 : (8*dst_length - ff_h264_decode_rbsp_trailing(h, ptr + dst_length - 1));
>> +
>> +        init_get_bits(&h->s.gb, ptr, bit_length);
>> +        switch(h->nal_unit_type){
>> +        case NAL_SPS:
>> +            ff_h264_decode_seq_parameter_set(h);
>> +            break;
>> +        case NAL_PPS:
>> +            ff_h264_decode_picture_parameter_set(h, h->s.gb.size_in_bits);
>> +            break;
>> +        case NAL_SEI:
>> +            ff_h264_decode_sei(h);
>> +            break;
>> +        case NAL_IDR_SLICE:
>> +        case NAL_SLICE:
>> +            get_ue_golomb(&h->s.gb);  // skip first_mb_in_slice
>> +            slice_type = get_ue_golomb_31(&h->s.gb) % 5;
>> +            *ppict_type= golomb_to_pict_type[slice_type];
>> +            *precovery_frame_cnt = h->sei_recovery_frame_cnt;
>> +            if (h->nal_unit_type == NAL_IDR_SLICE) {
>> +                /* this is an IDR key frame (mostly at begin of the stream) */
>> +                *pkey_frame = 1;
>> +            } else if (h->sei_recovery_frame_cnt >= 0) {
>> +                /* key frame, since recovery_frame_cnt is set */
>> +                *pkey_frame = 1;
>> +            }
>> +            pps_id= get_ue_golomb(&h->s.gb);
>> +            if(pps_id>=MAX_PPS_COUNT){
>> +                av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n");
>> +                return -1;
>> +            }
>> +            if(!h->pps_buffers[pps_id]) {
>> +                av_log(h->s.avctx, AV_LOG_ERROR, "non-existing PPS referenced\n");
>> +                return -1;
>> +            }
>> +            h->pps= *h->pps_buffers[pps_id];
>> +            if(!h->sps_buffers[h->pps.sps_id]) {
>> +                av_log(h->s.avctx, AV_LOG_ERROR, "non-existing SPS referenced\n");
>> +                return -1;
>> +            }
>> +            h->sps = *h->sps_buffers[h->pps.sps_id];
>> +            *pframe_num = get_bits(&h->s.gb, h->sps.log2_max_frame_num);
>> +            if (h->sps.frame_mbs_only_flag) {
>> +                /* single picture for a frame */
>> +                *pfield_pict = 0;
>> +            } else {
>> +                if (get_bits1(&h->s.gb)) {   /* field_pict_flag */
>> +                    /*
>> +                     * This frame is divided in two separate field pictures.
>> +                     * Field parity bit follows in picture header, but we
>> +                     * don't need it.
>> +                     */
>> +                    *pfield_pict = 1;
>> +                } else {
>> +                    *pfield_pict = 0;
>> +                }
>> +            }
>>     
>
> split the patch please so that
> IDR-keyframe
> SEI recovery
> field pics
>
> are in 3 seperate patches
> the original patch i wrote was not such an intermingled mix
>   
This is no intermingled mix. In the end, it would look exactly like 
this, whether in 3 patches or in 1 patch. It is an integral 
functionality (well, except for field pic, since this is still unused). 
I don't see the reason to split it (maybe except field pict flag / frame 
number, since this is unused yet), since this will obscure the intent of 
the patch - namely communicating key frames (independent of IDR or 
recovery point).

> [...]
>   
>> +/**
>> + * Set context parameters for lavf.
>> + *
>> + * @param s parser context.
>> + * @param pict_type picture type of the first slice in frame.
>> + * @param field_pict set to 1 for field picture, 0 for frame picture.
>> + * @param key_frame set to 1 for key pictures, 0 for non-key pictures.
>> + * @param recovery_frame_cnt frame count from SEI recovery point if present
>> + *              or -1 otherwise.
>> + * @param frame_num frame number.
>> + */
>> +static inline void h264_set_keyframe(AVCodecParserContext *s,
>> +                              int pict_type,
>> +                              int field_pict,
>> +                              int key_frame,
>> +                              int recovery_frame_cnt,
>> +                              int frame_num)
>> +{
>> +    /*
>> +     * NOTE: Currently, there is no flag to tell libavformat about
>> +     * key frames. Instead, it relies on having pict_type set to I
>> +     * for key frames, so we use this to communicate it. This should
>>     
>
> if your patch contains a hack like this its rejected.
> if theres a bug it has to be fixed, not worked around by such hacks
>   
I agree with you that bugs have to be fixed. However, I can not and will 
not, again, CAN NOT AND WILL NOT, fix all FFmpeg bugs and design errors, 
which are affecting my patches. Sometimes, there is time for a 
workaround, before other code is fixed (there are plenty in FFmpeg). 
Fixing this particular problem would entail adding two new fields (key 
frame and recovery count) to AVCodecParserContext, removing current key 
frame hack in compute_pkt_fields() and changing all format parsers to 
set key frame field, which is a lot of work and given current practices 
extremely high effort to box it through. I simply don't have time for 
that. I just wanted to help to support AVCHD camcorders, since this is 
my use case (and of a lot of other people willing to use AVCHD 
camcorders with Linux).

Your own code is full of FIXME comments and you don't have a problem 
with it. Why do you have a problem with it when someone else writes a 
patch which does the correct thing but due to deficiencies in other 
components needs to do a workaround? You are using different quality 
measurements for your own and foreign code, which I don't find OK.

Don't get me wrong, in general, I agree with you to minimize 
workarounds/hacks in the code, preferably to zero. I also looked at SVN 
log messages and patch sizes in files you maintain and I find it very 
good to have them so cleanly separated. But if you want to have 
progress, you'll have to accept *some* workarounds (which you do in your 
own code).

Since I'm feeling extremely unwelcome by FFmpeg developer community and 
lack of constructive criticism which spans more than a few words, I'm 
strongly considering to stop all my FFmpeg-related activities, make 
private patches that work for me and maintain them for me only (and 
eventually other people interested).

Please think about it, before scaring yet another promising dev 
community member away.

Regards,

Ivan





More information about the ffmpeg-devel mailing list