Browse code

hevc_parser: parse and export some stream parameters

Particularly those that will be needed by the QSV decoder.
More can be added later as necessary.

Anton Khirnov authored on 2015/07/10 02:34:51
Showing 3 changed files
... ...
@@ -2057,6 +2057,7 @@ wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
2057 2057
 
2058 2058
 # parsers
2059 2059
 h264_parser_select="h264_decoder"
2060
+hevc_parser_select="golomb"
2060 2061
 mpegvideo_parser_select="mpegvideo"
2061 2062
 mpeg4video_parser_select="error_resilience h263dsp mpeg_er mpegvideo qpeldsp"
2062 2063
 vc1_parser_select="mpegvideo startcode vc1_decoder"
... ...
@@ -697,7 +697,7 @@ OBJS-$(CONFIG_GSM_PARSER)              += gsm_parser.o
697 697
 OBJS-$(CONFIG_H261_PARSER)             += h261_parser.o
698 698
 OBJS-$(CONFIG_H263_PARSER)             += h263_parser.o
699 699
 OBJS-$(CONFIG_H264_PARSER)             += h264_parser.o
700
-OBJS-$(CONFIG_HEVC_PARSER)             += hevc_parser.o
700
+OBJS-$(CONFIG_HEVC_PARSER)             += hevc_parser.o hevc_parse.o
701 701
 OBJS-$(CONFIG_MJPEG_PARSER)            += mjpeg_parser.o
702 702
 OBJS-$(CONFIG_MLP_PARSER)              += mlp_parser.o mlp.o
703 703
 OBJS-$(CONFIG_MPEG4VIDEO_PARSER)       += mpeg4video_parser.o h263.o \
... ...
@@ -22,11 +22,99 @@
22 22
 
23 23
 #include "libavutil/common.h"
24 24
 
25
-#include "parser.h"
25
+#include "golomb.h"
26 26
 #include "hevc.h"
27
+#include "parser.h"
27 28
 
28 29
 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
29 30
 
31
+#define IS_IRAP_NAL(nal) (nal->type >= 16 && nal->type <= 23)
32
+
33
+typedef struct HEVCParserContext {
34
+    ParseContext pc;
35
+
36
+    HEVCPacket pkt;
37
+    HEVCParamSets ps;
38
+
39
+    int parsed_extradata;
40
+} HEVCParserContext;
41
+
42
+static int hevc_parse_slice_header(AVCodecParserContext *s, HEVCNAL *nal,
43
+                                   AVCodecContext *avctx)
44
+{
45
+    HEVCParserContext *ctx = s->priv_data;
46
+    GetBitContext *gb = &nal->gb;
47
+
48
+    HEVCPPS *pps;
49
+    HEVCSPS *sps;
50
+    unsigned int pps_id;
51
+
52
+    get_bits1(gb);          // first slice in pic
53
+    if (IS_IRAP_NAL(nal))
54
+        get_bits1(gb);      // no output of prior pics
55
+
56
+    pps_id = get_ue_golomb_long(gb);
57
+    if (pps_id >= MAX_PPS_COUNT || !ctx->ps.pps_list[pps_id]) {
58
+        av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id);
59
+        return AVERROR_INVALIDDATA;
60
+    }
61
+    pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data;
62
+    sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data;
63
+
64
+    /* export the stream parameters */
65
+    s->coded_width  = sps->width;
66
+    s->coded_height = sps->height;
67
+    s->width        = sps->output_width;
68
+    s->height       = sps->output_height;
69
+    s->format       = sps->pix_fmt;
70
+    avctx->profile  = sps->ptl.general_ptl.profile_idc;
71
+    avctx->level    = sps->ptl.general_ptl.level_idc;
72
+
73
+    /* ignore the rest for now*/
74
+
75
+    return 0;
76
+}
77
+
78
+static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
79
+                           int buf_size, AVCodecContext *avctx)
80
+{
81
+    HEVCParserContext *ctx = s->priv_data;
82
+    int ret, i;
83
+
84
+    ret = ff_hevc_split_packet(&ctx->pkt, buf, buf_size, avctx, 0, 0);
85
+    if (ret < 0)
86
+        return ret;
87
+
88
+    for (i = 0; i < ctx->pkt.nb_nals; i++) {
89
+        HEVCNAL *nal = &ctx->pkt.nals[i];
90
+
91
+        /* ignore everything except parameter sets and VCL NALUs */
92
+        switch (nal->type) {
93
+        case NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, avctx, &ctx->ps);    break;
94
+        case NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, avctx, &ctx->ps, 1); break;
95
+        case NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, avctx, &ctx->ps);    break;
96
+        case NAL_TRAIL_R:
97
+        case NAL_TRAIL_N:
98
+        case NAL_TSA_N:
99
+        case NAL_TSA_R:
100
+        case NAL_STSA_N:
101
+        case NAL_STSA_R:
102
+        case NAL_BLA_W_LP:
103
+        case NAL_BLA_W_RADL:
104
+        case NAL_BLA_N_LP:
105
+        case NAL_IDR_W_RADL:
106
+        case NAL_IDR_N_LP:
107
+        case NAL_CRA_NUT:
108
+        case NAL_RADL_N:
109
+        case NAL_RADL_R:
110
+        case NAL_RASL_N:
111
+        case NAL_RASL_R: hevc_parse_slice_header(s, nal, avctx); break;
112
+        }
113
+    }
114
+
115
+    return 0;
116
+}
117
+
30 118
 /**
31 119
  * Find the end of the current frame in the bitstream.
32 120
  * @return the position of the first byte of the next frame, or END_NOT_FOUND
... ...
@@ -34,8 +122,9 @@
34 34
 static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
35 35
                                int buf_size)
36 36
 {
37
+    HEVCParserContext *ctx = s->priv_data;
38
+    ParseContext       *pc = &ctx->pc;
37 39
     int i;
38
-    ParseContext *pc = s->priv_data;
39 40
 
40 41
     for (i = 0; i < buf_size; i++) {
41 42
         int nut;
... ...
@@ -76,7 +165,14 @@ static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx,
76 76
                       const uint8_t *buf, int buf_size)
77 77
 {
78 78
     int next;
79
-    ParseContext *pc = s->priv_data;
79
+
80
+    HEVCParserContext *ctx = s->priv_data;
81
+    ParseContext *pc = &ctx->pc;
82
+
83
+    if (avctx->extradata && !ctx->parsed_extradata) {
84
+        parse_nal_units(s, avctx->extradata, avctx->extradata_size, avctx);
85
+        ctx->parsed_extradata = 1;
86
+    }
80 87
 
81 88
     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
82 89
         next = buf_size;
... ...
@@ -89,6 +185,8 @@ static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx,
89 89
         }
90 90
     }
91 91
 
92
+    parse_nal_units(s, buf, buf_size, avctx);
93
+
92 94
     *poutbuf      = buf;
93 95
     *poutbuf_size = buf_size;
94 96
     return next;
... ...
@@ -116,10 +214,30 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
116 116
     return 0;
117 117
 }
118 118
 
119
+static void hevc_parser_close(AVCodecParserContext *s)
120
+{
121
+    HEVCParserContext *ctx = s->priv_data;
122
+    int i;
123
+
124
+    for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.vps_list); i++)
125
+        av_buffer_unref(&ctx->ps.vps_list[i]);
126
+    for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.sps_list); i++)
127
+        av_buffer_unref(&ctx->ps.sps_list[i]);
128
+    for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.pps_list); i++)
129
+        av_buffer_unref(&ctx->ps.pps_list[i]);
130
+
131
+    for (i = 0; i < ctx->pkt.nals_allocated; i++)
132
+        av_freep(&ctx->pkt.nals[i].rbsp_buffer);
133
+    av_freep(&ctx->pkt.nals);
134
+    ctx->pkt.nals_allocated = 0;
135
+
136
+    av_freep(&ctx->pc.buffer);
137
+}
138
+
119 139
 AVCodecParser ff_hevc_parser = {
120 140
     .codec_ids      = { AV_CODEC_ID_HEVC },
121
-    .priv_data_size = sizeof(ParseContext),
141
+    .priv_data_size = sizeof(HEVCParserContext),
122 142
     .parser_parse   = hevc_parse,
123
-    .parser_close   = ff_parse_close,
143
+    .parser_close   = hevc_parser_close,
124 144
     .split          = hevc_split,
125 145
 };