Browse code

h264_mp4toannexb_bsf: factor out extradata parsing

Luca Barbato authored on 2013/06/11 23:44:04
Showing 1 changed files
... ...
@@ -58,6 +58,79 @@ static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
58 58
     return 0;
59 59
 }
60 60
 
61
+static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding)
62
+{
63
+    uint16_t unit_size;
64
+    uint64_t total_size                 = 0;
65
+    uint8_t *out                        = NULL, unit_nb, sps_done = 0,
66
+             sps_seen                   = 0, pps_seen = 0;
67
+    const uint8_t *extradata            = avctx->extradata + 4;
68
+    static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
69
+    int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
70
+
71
+    if (length_size == 3)
72
+        return AVERROR(EINVAL);
73
+
74
+    /* retrieve sps and pps unit(s) */
75
+    unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
76
+    if (!unit_nb) {
77
+        unit_nb = *extradata++; /* number of pps unit(s) */
78
+        sps_done++;
79
+
80
+        if (unit_nb)
81
+            pps_seen = 1;
82
+    } else {
83
+        sps_seen = 1;
84
+    }
85
+
86
+    while (unit_nb--) {
87
+        void *tmp;
88
+
89
+        unit_size   = AV_RB16(extradata);
90
+        total_size += unit_size + 4;
91
+        if (total_size > INT_MAX - padding ||
92
+            extradata + 2 + unit_size > avctx->extradata +
93
+            avctx->extradata_size) {
94
+            av_free(out);
95
+            return AVERROR(EINVAL);
96
+        }
97
+        tmp = av_realloc(out, total_size + padding);
98
+        if (!tmp) {
99
+            av_free(out);
100
+            return AVERROR(ENOMEM);
101
+        }
102
+        out = tmp;
103
+        memcpy(out + total_size - unit_size - 4, nalu_header, 4);
104
+        memcpy(out + total_size - unit_size, extradata + 2, unit_size);
105
+        extradata += 2 + unit_size;
106
+
107
+        if (!unit_nb && !sps_done++) {
108
+            unit_nb = *extradata++; /* number of pps unit(s) */
109
+            if (unit_nb)
110
+                pps_seen = 1;
111
+        }
112
+    }
113
+
114
+    if (out)
115
+        memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
116
+
117
+    if (!sps_seen)
118
+        av_log(avctx, AV_LOG_WARNING,
119
+               "Warning: SPS NALU missing or invalid. "
120
+               "The resulting stream may not play.\n");
121
+
122
+    if (!pps_seen)
123
+        av_log(avctx, AV_LOG_WARNING,
124
+               "Warning: PPS NALU missing or invalid. "
125
+               "The resulting stream may not play.\n");
126
+
127
+    av_free(avctx->extradata);
128
+    avctx->extradata      = out;
129
+    avctx->extradata_size = total_size;
130
+
131
+    return length_size;
132
+}
133
+
61 134
 static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
62 135
                                    AVCodecContext *avctx, const char *args,
63 136
                                    uint8_t **poutbuf, int *poutbuf_size,
... ...
@@ -69,6 +142,7 @@ static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
69 69
     int32_t nal_size;
70 70
     uint32_t cumul_size    = 0;
71 71
     const uint8_t *buf_end = buf + buf_size;
72
+    int ret = 0;
72 73
 
73 74
     /* nothing to filter */
74 75
     if (!avctx->extradata || avctx->extradata_size < 6) {
... ...
@@ -79,74 +153,10 @@ static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
79 79
 
80 80
     /* retrieve sps and pps NAL units from extradata */
81 81
     if (!ctx->extradata_parsed) {
82
-        uint16_t unit_size;
83
-        uint64_t total_size                 = 0;
84
-        uint8_t *out                        = NULL, unit_nb, sps_done = 0,
85
-                 sps_seen                   = 0, pps_seen = 0;
86
-        const uint8_t *extradata            = avctx->extradata + 4;
87
-        static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
88
-
89
-        /* retrieve length coded size */
90
-        ctx->length_size = (*extradata++ & 0x3) + 1;
91
-        if (ctx->length_size == 3)
92
-            return AVERROR(EINVAL);
93
-
94
-        /* retrieve sps and pps unit(s) */
95
-        unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
96
-        if (!unit_nb) {
97
-            unit_nb = *extradata++; /* number of pps unit(s) */
98
-            sps_done++;
99
-
100
-            if (unit_nb)
101
-                pps_seen = 1;
102
-        } else {
103
-            sps_seen = 1;
104
-        }
105
-
106
-        while (unit_nb--) {
107
-            void *tmp;
108
-
109
-            unit_size   = AV_RB16(extradata);
110
-            total_size += unit_size + 4;
111
-            if (total_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE ||
112
-                extradata + 2 + unit_size > avctx->extradata +
113
-                avctx->extradata_size) {
114
-                av_free(out);
115
-                return AVERROR(EINVAL);
116
-            }
117
-            tmp = av_realloc(out, total_size + FF_INPUT_BUFFER_PADDING_SIZE);
118
-            if (!tmp) {
119
-                av_free(out);
120
-                return AVERROR(ENOMEM);
121
-            }
122
-            out = tmp;
123
-            memcpy(out + total_size - unit_size - 4, nalu_header, 4);
124
-            memcpy(out + total_size - unit_size, extradata + 2, unit_size);
125
-            extradata += 2 + unit_size;
126
-
127
-            if (!unit_nb && !sps_done++) {
128
-                unit_nb = *extradata++; /* number of pps unit(s) */
129
-                if (unit_nb)
130
-                    pps_seen = 1;
131
-            }
132
-        }
133
-
134
-        if (out)
135
-            memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
136
-
137
-        if (!sps_seen)
138
-            av_log(avctx, AV_LOG_WARNING,
139
-                   "Warning: SPS NALU missing or invalid. "
140
-                   "The resulting stream may not play.\n");
141
-
142
-        if (!pps_seen)
143
-            av_log(avctx, AV_LOG_WARNING,
144
-                   "Warning: PPS NALU missing or invalid. "
145
-                   "The resulting stream may not play.\n");
146
-
147
-        av_free(avctx->extradata);
148
-        avctx->extradata      = out;
149
-        avctx->extradata_size = total_size;
82
+        ret = h264_extradata_to_annexb(avctx, FF_INPUT_BUFFER_PADDING_SIZE);
83
+        if (ret < 0)
84
+            return ret;
85
+        ctx->length_size      = ret;
150 86
         ctx->first_idr        = 1;
151 87
         ctx->extradata_parsed = 1;
152 88
     }