Ticket #6243: H264Parser-fixes-v1.1.patch

File H264Parser-fixes-v1.1.patch, 12.2 KB (added by jppoet@…, 15 years ago)

Allows recorder to designate if I frames should be counted as keyframes

  • libs/libmythtv/mpeg/H264Parser.cpp

    old new  
    33
    44extern "C" {
    55// from libavcodec
    6     extern const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state);
     6    extern const uint8_t *ff_find_start_code(const uint8_t * p,
     7                                             const uint8_t *end,
     8                                             uint32_t * state);
    79#include "avcodec.h"
    810}
    911
    static const float eps = 1E-5; 
    8890H264Parser::H264Parser(void)
    8991{
    9092    Reset();
     93    I_is_keyframe = false;
    9194}
    9295
    9396void H264Parser::Reset(void)
    9497{
    9598    state_changed = false;
    96     seen_sps = seen_IDR = false;
     99    seen_sps = false;
     100    is_keyframe = false;
    97101
    98102    sync_accumulator = 0xffffffff;
    99     find_AU = false;
    100103    AU_pending = false;
    101104
    102     NAL_type = UNKNOWN;
    103 
    104105    frame_num = prev_frame_num = -1;
    105106    slice_type = SLICE_UNDEF;
    106107    prev_pic_parameter_set_id = pic_parameter_set_id = -1;
    void H264Parser::Reset(void) 
    112113    prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0;
    113114    prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0;
    114115    prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0;
    115     prev_nal_unit_type = nal_unit_type = 0;
     116    prev_nal_unit_type = nal_unit_type = UNKNOWN;
    116117    prev_idr_pic_id = idr_pic_id = 0;
    117118
    118119    log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0;
    void H264Parser::Reset(void) 
    136137
    137138    AU_offset = frame_start_offset = keyframe_start_offset = 0;
    138139    on_frame = on_key_frame = false;
    139 
    140     wait_for_IDR = false;
    141140}
    142141
    143142
    bool H264Parser::new_AU(void) 
    214213    {
    215214        // Need previous slice information for comparison
    216215
    217         if (NAL_type == AU_DELIMITER ||
    218             NAL_type == SPS ||
    219             NAL_type == PPS ||
    220             NAL_type == SEI ||
    221             (NAL_type > SPS_EXT && NAL_type < AUXILIARY_SLICE))
    222             result = true;
    223         else if (NAL_type != SLICE_IDR && frame_num != prev_frame_num)
     216        if (nal_unit_type != SLICE_IDR && frame_num != prev_frame_num)
    224217            result = true;
    225218        else if (prev_pic_parameter_set_id != -1 &&
    226219                 pic_parameter_set_id != prev_pic_parameter_set_id)
    bool H264Parser::new_AU(void) 
    230223        else if ((bottom_field_flag != -1 && prev_bottom_field_flag != -1) &&
    231224                 bottom_field_flag != prev_bottom_field_flag)
    232225            result = true;
    233         else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) &&
    234                  nal_ref_idc != prev_nal_ref_idc)
    235             result = true;
    236226        else if ((pic_order_cnt_type == 0 && prev_pic_order_cnt_type == 0) &&
    237227                 (pic_order_cnt_lsb != prev_pic_order_cnt_lsb ||
    238228                  delta_pic_order_cnt_bottom !=
    bool H264Parser::new_AU(void) 
    256246    prev_pic_parameter_set_id = pic_parameter_set_id;
    257247    prev_field_pic_flag = field_pic_flag;
    258248    prev_bottom_field_flag = bottom_field_flag;
    259     prev_nal_ref_idc = nal_ref_idc;
    260249    prev_pic_order_cnt_lsb = pic_order_cnt_lsb;
    261250    prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom;
    262251    prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0];
    uint32_t H264Parser::addBytes(const uint 
    273262{
    274263    const uint8_t *byteP = bytes;
    275264    const uint8_t *endP = bytes + byte_count;
    276 
     265    const uint8_t *nalP;
    277266    uint8_t        first_byte;
    278267
    279268    state_changed = false;
    uint32_t H264Parser::addBytes(const uint 
    305294  11 End of stream end_of_stream_rbsp( )
    306295*/
    307296            first_byte = *(byteP - 1);
    308             NAL_type = first_byte & 0x1f;
     297            nal_unit_type = first_byte & 0x1f;
    309298            nal_ref_idc = (first_byte >> 5) & 0x3;
    310299
    311             if (NALisSlice(NAL_type) || NAL_type == SPS || NAL_type == PPS)
     300            if (nal_unit_type == SPS || nal_unit_type == PPS ||
     301                nal_unit_type == SEI || NALisSlice(nal_unit_type))
    312302            {
    313303                /*
    314304                  bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE
    uint32_t H264Parser::addBytes(const uint 
    318308                {
    319309                    init_get_bits(&gb, byteP, 8 * (endP - byteP));
    320310
    321                     if (NAL_type == SPS)
     311                    if (nal_unit_type == SEI)
     312                    {
     313                        nalP = ff_find_start_code(byteP+1, endP,
     314                                                  &sync_accumulator) - 8;
     315                        decode_SEI(&gb, (nalP - byteP) * 8);
     316                        set_AU_pending(stream_offset);
     317                    }
     318                    else if (nal_unit_type == SPS)
     319                    {
    322320                        decode_SPS(&gb);
    323                     else if (NAL_type == PPS)
     321                        set_AU_pending(stream_offset);
     322                    }
     323                    else if (nal_unit_type == PPS)
     324                    {
    324325                        decode_PPS(&gb);
     326                        set_AU_pending(stream_offset);
     327                    }
    325328                    else
    326                         find_AU = decode_Header(&gb);
     329                    {
     330                        decode_Header(&gb);
     331                        if (new_AU())
     332                            set_AU_pending(stream_offset);
     333                    }
    327334
    328335                    byteP += (get_bits_count(&gb) / 8);
    329336                }
    330337            }
    331 
    332             if (find_AU && new_AU())
     338            else if (!AU_pending)
    333339            {
    334                 /* After finding a new AU, don't look for another one
    335                    until we decode a SLICE */
    336                 find_AU = false;
    337                 AU_pending = true;
    338                 AU_offset = stream_offset;
     340                if (nal_unit_type == AU_DELIMITER ||
     341                    (nal_unit_type > SPS_EXT &&
     342                     nal_unit_type < AUXILIARY_SLICE))
     343                {
     344                    AU_pending = true;
     345                    AU_offset = stream_offset;
     346                }
     347                else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) &&
     348                         nal_ref_idc != prev_nal_ref_idc)
     349                {
     350                    AU_pending = true;
     351                    AU_offset = stream_offset;
     352                }
    339353            }
    340            
    341             if (AU_pending && NALisSlice(NAL_type))
     354
     355            if (AU_pending && NALisSlice(nal_unit_type))
    342356            {
    343357                /* Once we know the slice type of a new AU, we can
    344358                 * determine if it is a keyframe or just a frame */
    uint32_t H264Parser::addBytes(const uint 
    349363                on_frame = true;
    350364                frame_start_offset = AU_offset;
    351365
    352                 if (isKeySlice(slice_type) && (!wait_for_IDR || seen_IDR))
     366                if (is_keyframe)
    353367                {
    354368                    on_key_frame = true;
    355369                    keyframe_start_offset = AU_offset;
     370                    is_keyframe = false;
    356371                }
    357372                else
    358373                    on_key_frame = false;
    uint32_t H264Parser::addBytes(const uint 
    360375            else
    361376                on_frame = on_key_frame = false;
    362377
     378            prev_nal_ref_idc = nal_ref_idc;
     379
    363380            return byteP - bytes;
    364381        }
    365382    }
    bool H264Parser::decode_Header(GetBitCon 
    440457    */
    441458
    442459    frame_num = get_bits(gb, log2_max_frame_num);
    443     if (NAL_type == SLICE_IDR || frame_num == 0)
    444         seen_IDR = true;
    445460
    446461    /*
    447462      field_pic_flag equal to 1 specifies that the slice is a slice of a
    bool H264Parser::decode_Header(GetBitCon 
    475490      second such IDR access unit. The value of idr_pic_id shall be in
    476491      the range of 0 to 65535, inclusive.
    477492     */
     493
    478494    if (nal_unit_type == SLICE_IDR)
     495    {
     496        is_keyframe = true;
    479497        idr_pic_id = get_ue_golomb(gb);
     498    }
     499    else
     500        is_keyframe |= (I_is_keyframe && isKeySlice(slice_type));
    480501
    481502    /*
    482503      pic_order_cnt_lsb specifies the picture order count modulo
    void H264Parser::decode_PPS(GetBitContex 
    806827#endif
    807828}
    808829
     830void H264Parser::decode_SEI(GetBitContext * gb, int bitlen)
     831{
     832    int   recovery_frame_cnt = -1;
     833    bool  exact_match_flag = false;
     834    bool  broken_link_flag = false;
     835    int   changing_group_slice_idc = -1;
     836
     837    while (get_bits_count(gb) < bitlen)
     838    {
     839        int type = 0, size = 0;
     840
     841        do {
     842            type += show_bits(gb, 8);
     843        } while (get_bits(gb, 8) == 255);
     844
     845        do {
     846            size += show_bits(gb, 8);
     847        } while (get_bits(gb, 8) == 255);
     848
     849        switch (type)
     850        {
     851          case SEI_TYPE_RECOVERY_POINT:
     852            recovery_frame_cnt = get_ue_golomb(gb);
     853            exact_match_flag = get_bits1(gb);
     854            broken_link_flag = get_bits1(gb);
     855            changing_group_slice_idc = get_bits(gb, 2);
     856            is_keyframe |= (recovery_frame_cnt >= 0);
     857            return;
     858
     859          default:
     860            skip_bits(gb, size * 8);
     861            break;
     862        }
     863
     864        align_get_bits(gb);
     865    }
     866}
     867
    809868void H264Parser::vui_parameters(GetBitContext * gb)
    810869{
    811870    /*
  • libs/libmythtv/mpeg/H264Parser.h

    old new class H264Parser { 
    5353        AUXILIARY_SLICE = 19
    5454    };
    5555
     56    enum SEI_type {
     57        SEI_TYPE_PIC_TIMING             = 1,
     58        SEI_TYPE_USER_DATA_UNREGISTERED = 5,
     59        SEI_TYPE_RECOVERY_POINT         = 6
     60    };
     61
    5662    /*
    5763      slice_type values in the range 5..9 specify, in addition to the
    5864      coding type of the current slice, that all other slices of the
    class H264Parser { 
    9096
    9197    bool stateChanged(void) const { return state_changed; }
    9298
    93     // seenIDR implies that a SPS has also been seen
    94     bool seenIDR(void) const { return seen_IDR; }
    95     uint8_t lastNALtype(void) const { return NAL_type; }
     99    uint8_t lastNALtype(void) const { return nal_unit_type; }
    96100
    97101    frame_type FieldType(void) const
    98102        {
    class H264Parser { 
    130134                    nal_type == SLICE_IDR);
    131135        }
    132136
    133     void waitForIDR(bool wait) { wait_for_IDR = wait; }
     137    void use_I_forKeyframes(bool val) { I_is_keyframe = val; }
    134138
    135139  private:
    136140    enum constants {EXTENDED_SAR = 255};
    137141
    138     bool is_first_VCL_NAL_unit(void);
     142    inline void set_AU_pending(const uint64_t & stream_offset)
     143        {
     144            if (!AU_pending)
     145            {
     146                AU_pending = true;
     147                AU_offset = stream_offset;
     148            }
     149        }
     150
    139151    bool new_AU(void);
    140152    bool decode_Header(GetBitContext *gb);
    141153    void decode_SPS(GetBitContext *gb);
    142154    void decode_PPS(GetBitContext * gb);
     155    void decode_SEI(GetBitContext * gb, int len);
    143156    void vui_parameters(GetBitContext * gb);
    144157
    145     bool       find_AU;
    146158    bool       AU_pending;
    147159    bool       state_changed;
    148160    bool       seen_sps;
    149     bool       seen_IDR;
     161    bool       is_keyframe;
     162    bool       I_is_keyframe;
    150163
    151164    uint32_t   sync_accumulator;
    152165    GetBitContext gb;
    153166
    154     uint8_t    NAL_type;
    155 
    156167    int        prev_frame_num, frame_num;
    157168    uint       slice_type;
    158169    int        prev_pic_parameter_set_id, pic_parameter_set_id;
    class H264Parser { 
    188199
    189200    uint64_t   AU_offset, frame_start_offset, keyframe_start_offset;
    190201    bool       on_frame, on_key_frame;
    191 
    192     bool       wait_for_IDR;
    193202};
    194203
    195204#endif /* H264PARSER_H */
  • libs/libmythtv/mpegrecorder.cpp

    old new bool MpegRecorder::OpenV4L2DeviceAsInput 
    423423            bzero(_stream_id,  sizeof(_stream_id));
    424424            bzero(_pid_status, sizeof(_pid_status));
    425425            memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
     426            m_h264_parser.use_I_forKeyframes(true);
    426427        }
    427428        else
    428429        {
    void MpegRecorder::ResetForNewFile(void) 
    13731374    bzero(_stream_id,  sizeof(_stream_id));
    13741375    bzero(_pid_status, sizeof(_pid_status));
    13751376    memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
    1376 
    1377     m_h264_parser.waitForIDR(true);
    13781377}
    13791378
    13801379void MpegRecorder::Reset(void)