avcodec/hevc_parser: Reenable the old parser under ADVANCED_PARSER define
authorMichael Niedermayer <michael@niedermayer.cc>
Mon, 13 Jul 2015 00:07:15 +0000 (02:07 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Mon, 13 Jul 2015 00:14:58 +0000 (02:14 +0200)
Feel free to use either, they both work but the old one provides
more information but needs the hevc decoder

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavcodec/hevc_parser.c

index fee13a8..77ca017 100644 (file)
@@ -30,6 +30,8 @@
 
 #define IS_IRAP_NAL(nal) (nal->type >= 16 && nal->type <= 23)
 
+#define ADVANCED_PARSER
+
 typedef struct HEVCParserContext {
     ParseContext pc;
 
@@ -37,6 +39,10 @@ typedef struct HEVCParserContext {
     HEVCParamSets ps;
 
     int parsed_extradata;
+
+#ifdef ADVANCED_PARSER
+    HEVCContext h;
+#endif
 } HEVCParserContext;
 
 static int hevc_parse_slice_header(AVCodecParserContext *s, HEVCNAL *nal,
@@ -75,6 +81,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, HEVCNAL *nal,
     return 0;
 }
 
+#ifndef ADVANCED_PARSER
 static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
                            int buf_size, AVCodecContext *avctx)
 {
@@ -114,6 +121,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
 
     return 0;
 }
+#endif
 
 /**
  * Find the end of the current frame in the bitstream.
@@ -166,180 +174,190 @@ static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
  * @param buf buffer with field/frame data.
  * @param buf_size size of the buffer.
  */
-// static inline int parse_nal_unitsX(AVCodecParserContext *s, AVCodecContext *avctx,
-//                       const uint8_t *buf, int buf_size)
-// {
-//     HEVCContext   *h  = &((HEVCParseContext *)s->priv_data)->h;
-//     GetBitContext *gb = &h->HEVClc->gb;
-//     SliceHeader   *sh = &h->sh;
-//     HEVCParamSets *ps = &h->ps;
-//     HEVCPacket   *pkt = &h->pkt;
-//     const uint8_t *buf_end = buf + buf_size;
-//     int state = -1, i;
-//     HEVCNAL *nal;
-//
-//     /* set some sane default values */
-//     s->pict_type         = AV_PICTURE_TYPE_I;
-//     s->key_frame         = 0;
-//     s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
-//
-//     h->avctx = avctx;
-//
-//     if (!buf_size)
-//         return 0;
-//
-//     if (pkt->nals_allocated < 1) {
-//         HEVCNAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
-//         if (!tmp)
-//             return AVERROR(ENOMEM);
-//         pkt->nals = tmp;
-//         memset(pkt->nals, 0, sizeof(*tmp));
-//         pkt->nals_allocated = 1;
-//     }
-//
-//     nal = &pkt->nals[0];
-//
-//     for (;;) {
-//         int src_length, consumed;
-//         buf = avpriv_find_start_code(buf, buf_end, &state);
-//         if (--buf + 2 >= buf_end)
-//             break;
-//         src_length = buf_end - buf;
-//
-//         h->nal_unit_type = (*buf >> 1) & 0x3f;
-//         h->temporal_id   = (*(buf + 1) & 0x07) - 1;
-//         if (h->nal_unit_type <= NAL_CRA_NUT) {
-//             // Do not walk the whole buffer just to decode slice segment header
-//             if (src_length > 20)
-//                 src_length = 20;
-//         }
-//
-//         consumed = ff_hevc_extract_rbsp(h, buf, src_length, nal);
-//         if (consumed < 0)
-//             return consumed;
-//
-//         init_get_bits8(gb, nal->data + 2, nal->size);
-//         switch (h->nal_unit_type) {
-//         case NAL_VPS:
-//             ff_hevc_decode_nal_vps(gb, avctx, ps);
-//             break;
-//         case NAL_SPS:
-//             ff_hevc_decode_nal_sps(gb, avctx, ps, h->apply_defdispwin);
-//             break;
-//         case NAL_PPS:
-//             ff_hevc_decode_nal_pps(gb, avctx, ps);
-//             break;
-//         case NAL_SEI_PREFIX:
-//         case NAL_SEI_SUFFIX:
-//             ff_hevc_decode_nal_sei(h);
-//             break;
-//         case NAL_TRAIL_N:
-//         case NAL_TRAIL_R:
-//         case NAL_TSA_N:
-//         case NAL_TSA_R:
-//         case NAL_STSA_N:
-//         case NAL_STSA_R:
-//         case NAL_RADL_N:
-//         case NAL_RADL_R:
-//         case NAL_RASL_N:
-//         case NAL_RASL_R:
-//         case NAL_BLA_W_LP:
-//         case NAL_BLA_W_RADL:
-//         case NAL_BLA_N_LP:
-//         case NAL_IDR_W_RADL:
-//         case NAL_IDR_N_LP:
-//         case NAL_CRA_NUT:
-//             sh->first_slice_in_pic_flag = get_bits1(gb);
-//             s->picture_structure = h->picture_struct;
-//             s->field_order = h->picture_struct;
-//
-//             if (IS_IRAP(h)) {
-//                 s->key_frame = 1;
-//                 sh->no_output_of_prior_pics_flag = get_bits1(gb);
-//             }
-//
-//             sh->pps_id = get_ue_golomb(gb);
-//             if (sh->pps_id >= MAX_PPS_COUNT || !ps->pps_list[sh->pps_id]) {
-//                 av_log(h->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id);
-//                 return AVERROR_INVALIDDATA;
-//             }
-//             ps->pps = (HEVCPPS*)ps->pps_list[sh->pps_id]->data;
-//
-//             if (ps->pps->sps_id >= MAX_SPS_COUNT || !ps->sps_list[ps->pps->sps_id]) {
-//                 av_log(h->avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", ps->pps->sps_id);
-//                 return AVERROR_INVALIDDATA;
-//             }
-//             if (ps->sps != (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data) {
-//                 ps->sps = (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data;
-//                 ps->vps = (HEVCVPS*)ps->vps_list[ps->sps->vps_id]->data;
-//             }
-//
-//             if (!sh->first_slice_in_pic_flag) {
-//                 int slice_address_length;
-//
-//                 if (ps->pps->dependent_slice_segments_enabled_flag)
-//                     sh->dependent_slice_segment_flag = get_bits1(gb);
-//                 else
-//                     sh->dependent_slice_segment_flag = 0;
-//
-//                 slice_address_length = av_ceil_log2_c(ps->sps->ctb_width *
-//                                                       ps->sps->ctb_height);
-//                 sh->slice_segment_addr = slice_address_length ? get_bits(gb, slice_address_length) : 0;
-//                 if (sh->slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) {
-//                     av_log(h->avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n",
-//                            sh->slice_segment_addr);
-//                     return AVERROR_INVALIDDATA;
-//                 }
-//             } else
-//                 sh->dependent_slice_segment_flag = 0;
-//
-//             if (sh->dependent_slice_segment_flag)
-//                 break;
-//
-//             for (i = 0; i < ps->pps->num_extra_slice_header_bits; i++)
-//                 skip_bits(gb, 1); // slice_reserved_undetermined_flag[]
-//
-//             sh->slice_type = get_ue_golomb(gb);
-//             if (!(sh->slice_type == I_SLICE || sh->slice_type == P_SLICE ||
-//                   sh->slice_type == B_SLICE)) {
-//                 av_log(h->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n",
-//                        sh->slice_type);
-//                 return AVERROR_INVALIDDATA;
-//             }
-//             s->pict_type = sh->slice_type == B_SLICE ? AV_PICTURE_TYPE_B :
-//                            sh->slice_type == P_SLICE ? AV_PICTURE_TYPE_P :
-//                                                        AV_PICTURE_TYPE_I;
-//
-//             if (ps->pps->output_flag_present_flag)
-//                 sh->pic_output_flag = get_bits1(gb);
-//
-//             if (ps->sps->separate_colour_plane_flag)
-//                 sh->colour_plane_id = get_bits(gb, 2);
-//
-//             if (!IS_IDR(h)) {
-//                 sh->pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb);
-//                 s->output_picture_number = h->poc = ff_hevc_compute_poc(h, sh->pic_order_cnt_lsb);
-//             } else
-//                 s->output_picture_number = h->poc = 0;
-//
-//             if (h->temporal_id == 0 &&
-//                 h->nal_unit_type != NAL_TRAIL_N &&
-//                 h->nal_unit_type != NAL_TSA_N &&
-//                 h->nal_unit_type != NAL_STSA_N &&
-//                 h->nal_unit_type != NAL_RADL_N &&
-//                 h->nal_unit_type != NAL_RASL_N &&
-//                 h->nal_unit_type != NAL_RADL_R &&
-//                 h->nal_unit_type != NAL_RASL_R)
-//                 h->pocTid0 = h->poc;
-//
-//             return 0; /* no need to evaluate the rest */
-//         }
-//         buf += consumed;
-//     }
-//     /* didn't find a picture! */
-//     av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n");
-//     return -1;
-// }
+#ifdef ADVANCED_PARSER
+static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
+                           int buf_size, AVCodecContext *avctx)
+{
+    HEVCParserContext *ctx = s->priv_data;
+    HEVCContext       *h   = &ctx->h;
+    GetBitContext      *gb;
+    SliceHeader        *sh = &h->sh;
+    HEVCParamSets *ps = &h->ps;
+    HEVCPacket   *pkt = &h->pkt;
+    const uint8_t *buf_end = buf + buf_size;
+    int state = -1, i;
+    HEVCNAL *nal;
+
+    if (!h->HEVClc)
+        h->HEVClc = av_mallocz(sizeof(HEVCLocalContext));
+    if (!h->HEVClc)
+        return AVERROR(ENOMEM);
+
+    gb = &h->HEVClc->gb;
+
+    /* set some sane default values */
+    s->pict_type         = AV_PICTURE_TYPE_I;
+    s->key_frame         = 0;
+    s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
+
+    h->avctx = avctx;
+
+    if (!buf_size)
+        return 0;
+
+    if (pkt->nals_allocated < 1) {
+        HEVCNAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
+        if (!tmp)
+            return AVERROR(ENOMEM);
+        pkt->nals = tmp;
+        memset(pkt->nals, 0, sizeof(*tmp));
+        pkt->nals_allocated = 1;
+    }
+
+    nal = &pkt->nals[0];
+
+    for (;;) {
+        int src_length, consumed;
+        buf = avpriv_find_start_code(buf, buf_end, &state);
+        if (--buf + 2 >= buf_end)
+            break;
+        src_length = buf_end - buf;
+
+        h->nal_unit_type = (*buf >> 1) & 0x3f;
+        h->temporal_id   = (*(buf + 1) & 0x07) - 1;
+        if (h->nal_unit_type <= NAL_CRA_NUT) {
+            // Do not walk the whole buffer just to decode slice segment header
+            if (src_length > 20)
+                src_length = 20;
+        }
+
+        consumed = ff_hevc_extract_rbsp(NULL, buf, src_length, nal);
+        if (consumed < 0)
+            return consumed;
+
+        init_get_bits8(gb, nal->data + 2, nal->size);
+        switch (h->nal_unit_type) {
+        case NAL_VPS:
+            ff_hevc_decode_nal_vps(gb, avctx, ps);
+            break;
+        case NAL_SPS:
+            ff_hevc_decode_nal_sps(gb, avctx, ps, 1);
+            break;
+        case NAL_PPS:
+            ff_hevc_decode_nal_pps(gb, avctx, ps);
+            break;
+        case NAL_SEI_PREFIX:
+        case NAL_SEI_SUFFIX:
+            ff_hevc_decode_nal_sei(h);
+            break;
+        case NAL_TRAIL_N:
+        case NAL_TRAIL_R:
+        case NAL_TSA_N:
+        case NAL_TSA_R:
+        case NAL_STSA_N:
+        case NAL_STSA_R:
+        case NAL_RADL_N:
+        case NAL_RADL_R:
+        case NAL_RASL_N:
+        case NAL_RASL_R:
+        case NAL_BLA_W_LP:
+        case NAL_BLA_W_RADL:
+        case NAL_BLA_N_LP:
+        case NAL_IDR_W_RADL:
+        case NAL_IDR_N_LP:
+        case NAL_CRA_NUT:
+            sh->first_slice_in_pic_flag = get_bits1(gb);
+            s->picture_structure = h->picture_struct;
+            s->field_order = h->picture_struct;
+
+            if (IS_IRAP(h)) {
+                s->key_frame = 1;
+                sh->no_output_of_prior_pics_flag = get_bits1(gb);
+            }
+
+            sh->pps_id = get_ue_golomb(gb);
+            if (sh->pps_id >= MAX_PPS_COUNT || !ps->pps_list[sh->pps_id]) {
+                av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id);
+                return AVERROR_INVALIDDATA;
+            }
+            ps->pps = (HEVCPPS*)ps->pps_list[sh->pps_id]->data;
+
+            if (ps->pps->sps_id >= MAX_SPS_COUNT || !ps->sps_list[ps->pps->sps_id]) {
+                av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", ps->pps->sps_id);
+                return AVERROR_INVALIDDATA;
+            }
+            if (ps->sps != (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data) {
+                ps->sps = (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data;
+                ps->vps = (HEVCVPS*)ps->vps_list[ps->sps->vps_id]->data;
+            }
+
+            if (!sh->first_slice_in_pic_flag) {
+                int slice_address_length;
+
+                if (ps->pps->dependent_slice_segments_enabled_flag)
+                    sh->dependent_slice_segment_flag = get_bits1(gb);
+                else
+                    sh->dependent_slice_segment_flag = 0;
+
+                slice_address_length = av_ceil_log2_c(ps->sps->ctb_width *
+                                                      ps->sps->ctb_height);
+                sh->slice_segment_addr = slice_address_length ? get_bits(gb, slice_address_length) : 0;
+                if (sh->slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) {
+                    av_log(avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n",
+                           sh->slice_segment_addr);
+                    return AVERROR_INVALIDDATA;
+                }
+            } else
+                sh->dependent_slice_segment_flag = 0;
+
+            if (sh->dependent_slice_segment_flag)
+                break;
+
+            for (i = 0; i < ps->pps->num_extra_slice_header_bits; i++)
+                skip_bits(gb, 1); // slice_reserved_undetermined_flag[]
+
+            sh->slice_type = get_ue_golomb(gb);
+            if (!(sh->slice_type == I_SLICE || sh->slice_type == P_SLICE ||
+                  sh->slice_type == B_SLICE)) {
+                av_log(avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n",
+                       sh->slice_type);
+                return AVERROR_INVALIDDATA;
+            }
+            s->pict_type = sh->slice_type == B_SLICE ? AV_PICTURE_TYPE_B :
+                           sh->slice_type == P_SLICE ? AV_PICTURE_TYPE_P :
+                                                       AV_PICTURE_TYPE_I;
+
+            if (ps->pps->output_flag_present_flag)
+                sh->pic_output_flag = get_bits1(gb);
+
+            if (ps->sps->separate_colour_plane_flag)
+                sh->colour_plane_id = get_bits(gb, 2);
+
+            if (!IS_IDR(h)) {
+                sh->pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb);
+                s->output_picture_number = h->poc = ff_hevc_compute_poc(h, sh->pic_order_cnt_lsb);
+            } else
+                s->output_picture_number = h->poc = 0;
+
+            if (h->temporal_id == 0 &&
+                h->nal_unit_type != NAL_TRAIL_N &&
+                h->nal_unit_type != NAL_TSA_N &&
+                h->nal_unit_type != NAL_STSA_N &&
+                h->nal_unit_type != NAL_RADL_N &&
+                h->nal_unit_type != NAL_RASL_N &&
+                h->nal_unit_type != NAL_RADL_R &&
+                h->nal_unit_type != NAL_RASL_R)
+                h->pocTid0 = h->poc;
+
+            return 0; /* no need to evaluate the rest */
+        }
+        buf += consumed;
+    }
+    /* didn't find a picture! */
+    av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n");
+    return -1;
+}
+#endif
 
 static int hevc_parse(AVCodecParserContext *s,
                       AVCodecContext *avctx,
@@ -400,6 +418,11 @@ static void hevc_parser_close(AVCodecParserContext *s)
     HEVCParserContext *ctx = s->priv_data;
     int i;
 
+#ifdef ADVANCED_PARSER
+    HEVCContext  *h  = &ctx->h;
+    av_freep(&h->HEVClc);
+#endif
+
     for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.vps_list); i++)
         av_buffer_unref(&ctx->ps.vps_list[i]);
     for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.sps_list); i++)