Browse code

avc: Add a function for converting mp4 style extradata to annex b

Make movenc use this function instead of the current custom
conversion function.

Signed-off-by: Martin Storsjö <martin@martin.st>

Martin Storsjö authored on 2012/03/22 20:25:58
Showing 3 changed files
... ...
@@ -160,3 +160,34 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
160 160
     }
161 161
     return 0;
162 162
 }
163
+
164
+int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
165
+{
166
+    uint16_t sps_size, pps_size;
167
+    uint8_t *out;
168
+    int out_size;
169
+
170
+    *buf = NULL;
171
+    if (*size >= 4 && (AV_RB32(in) == 0x00000001 || AV_RB24(in) == 0x000001))
172
+        return 0;
173
+    if (*size < 11 || in[0] != 1)
174
+        return AVERROR_INVALIDDATA;
175
+
176
+    sps_size = AV_RB16(&in[6]);
177
+    if (11 + sps_size > *size)
178
+        return AVERROR_INVALIDDATA;
179
+    pps_size = AV_RB16(&in[9 + sps_size]);
180
+    if (11 + sps_size + pps_size > *size)
181
+        return AVERROR_INVALIDDATA;
182
+    out_size = 8 + sps_size + pps_size;
183
+    out = av_mallocz(out_size);
184
+    if (!out)
185
+        return AVERROR(ENOMEM);
186
+    AV_WB32(&out[0], 0x00000001);
187
+    memcpy(out + 4, &in[8], sps_size);
188
+    AV_WB32(&out[4 + sps_size], 0x00000001);
189
+    memcpy(out + 8 + sps_size, &in[11 + sps_size], pps_size);
190
+    *buf = out;
191
+    *size = out_size;
192
+    return 0;
193
+}
... ...
@@ -29,5 +29,6 @@ int ff_avc_parse_nal_units(AVIOContext *s, const uint8_t *buf, int size);
29 29
 int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size);
30 30
 int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len);
31 31
 const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end);
32
+int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size);
32 33
 
33 34
 #endif /* AVFORMAT_AVC_H */
... ...
@@ -2096,26 +2096,6 @@ static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *va
2096 2096
     avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf);
2097 2097
 }
2098 2098
 
2099
-static void write_h264_extradata(AVIOContext *pb, AVCodecContext *enc)
2100
-{
2101
-    uint16_t sps_size, pps_size, len;
2102
-    char buf[150];
2103
-    sps_size = AV_RB16(&enc->extradata[6]);
2104
-    if (11 + sps_size > enc->extradata_size)
2105
-        return;
2106
-    pps_size = AV_RB16(&enc->extradata[9 + sps_size]);
2107
-    if (11 + sps_size + pps_size > enc->extradata_size)
2108
-        return;
2109
-    len = FFMIN(sizeof(buf)/2 - 1, sps_size);
2110
-    ff_data_to_hex(buf, &enc->extradata[8], len, 0);
2111
-    buf[2*len] = '\0';
2112
-    avio_printf(pb, "<param name=\"CodecPrivateData\" value=\"00000001%s", buf);
2113
-    len = FFMIN(sizeof(buf)/2 - 1, pps_size);
2114
-    ff_data_to_hex(buf, &enc->extradata[11 + sps_size], len, 0);
2115
-    buf[2*len] = '\0';
2116
-    avio_printf(pb, "00000001%s\" valuetype=\"data\"/>\n", buf);
2117
-}
2118
-
2119 2099
 static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
2120 2100
 {
2121 2101
     int64_t pos = avio_tell(pb);
... ...
@@ -2157,10 +2137,16 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
2157 2157
         param_write_int(pb, "systemBitrate", track->enc->bit_rate);
2158 2158
         param_write_int(pb, "trackID", track_id);
2159 2159
         if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
2160
-            if (track->enc->codec_id == CODEC_ID_H264 &&
2161
-                track->enc->extradata_size >= 11 &&
2162
-                track->enc->extradata[0] == 1) {
2163
-                write_h264_extradata(pb, track->enc);
2160
+            if (track->enc->codec_id == CODEC_ID_H264) {
2161
+                uint8_t *ptr;
2162
+                int size = track->enc->extradata_size;
2163
+                if (!ff_avc_write_annexb_extradata(track->enc->extradata, &ptr,
2164
+                                                   &size)) {
2165
+                    param_write_hex(pb, "CodecPrivateData",
2166
+                                    ptr ? ptr : track->enc->extradata,
2167
+                                    size);
2168
+                    av_free(ptr);
2169
+                }
2164 2170
             } else {
2165 2171
                 param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
2166 2172
                                 track->enc->extradata_size);