libx265: Use the repeat headers flag when not using global headers
authorMarcus Gustafsson <mankan@lysator.liu.se>
Tue, 25 Mar 2014 20:51:21 +0000 (21:51 +0100)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Mon, 31 Mar 2014 15:24:05 +0000 (16:24 +0100)
This allows proper muxing and seeking in things like MPEG-TS, by
placing headers by random access points.

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
libavcodec/libx265.c

index b124070..77d0b03 100644 (file)
@@ -38,8 +38,6 @@ typedef struct libx265Context {
 
     x265_encoder *encoder;
     x265_param   *params;
-    uint8_t      *header;
-    int           header_size;
 
     char *preset;
     char *tune;
@@ -66,7 +64,6 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx)
     libx265Context *ctx = avctx->priv_data;
 
     av_frame_free(&avctx->coded_frame);
-    av_freep(&ctx->header);
 
     x265_param_free(ctx->params);
 
@@ -82,8 +79,6 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx)
     x265_nal *nal;
     int sar_num, sar_den;
     int nnal;
-    int ret;
-    int i;
 
     if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL &&
         !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w &&
@@ -147,6 +142,9 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx)
         ctx->params->rc.rateControlMode = X265_RC_ABR;
     }
 
+    if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER))
+        ctx->params->bRepeatHeaders = 1;
+
     if (ctx->x265_opts) {
         AVDictionary *dict    = NULL;
         AVDictionaryEntry *en = NULL;
@@ -179,32 +177,23 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx)
         return AVERROR_INVALIDDATA;
     }
 
-    ret = x265_encoder_headers(ctx->encoder, &nal, &nnal);
-    if (ret < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
-        libx265_encode_close(avctx);
-        return AVERROR_INVALIDDATA;
-    }
-
-    for (i = 0; i < nnal; i++)
-        ctx->header_size += nal[i].sizeBytes;
-
-    ctx->header = av_malloc(ctx->header_size + FF_INPUT_BUFFER_PADDING_SIZE);
-    if (!ctx->header) {
-        av_log(avctx, AV_LOG_ERROR,
-               "Cannot allocate HEVC header of size %d.\n", ctx->header_size);
-        libx265_encode_close(avctx);
-        return AVERROR(ENOMEM);
-    }
-
-    memcpy(ctx->header, nal[0].payload, ctx->header_size);
-
     if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
-        avctx->extradata_size = ctx->header_size;
-        avctx->extradata      = ctx->header;
+        avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal);
+        if (avctx->extradata_size <= 0) {
+            av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
+            libx265_encode_close(avctx);
+            return AVERROR_INVALIDDATA;
+        }
 
-        ctx->header_size = 0;
-        ctx->header      = NULL;
+        avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!avctx->extradata) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size);
+            libx265_encode_close(avctx);
+            return AVERROR(ENOMEM);
+        }
+
+        memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size);
     }
 
     return 0;
@@ -246,8 +235,6 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     for (i = 0; i < nnal; i++)
         payload += nal[i].sizeBytes;
 
-    payload += ctx->header_size;
-
     ret = ff_alloc_packet(pkt, payload);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
@@ -255,14 +242,6 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     }
     dst = pkt->data;
 
-    if (ctx->header) {
-        memcpy(dst, ctx->header, ctx->header_size);
-        dst += ctx->header_size;
-
-        av_freep(&ctx->header);
-        ctx->header_size = 0;
-    }
-
     for (i = 0; i < nnal; i++) {
         memcpy(dst, nal[i].payload, nal[i].sizeBytes);
         dst += nal[i].sizeBytes;