[FFmpeg-devel] [PATCH] qsvenc: write a53 caption data to SEI
Will Kelleher
wkelleher at gogoair.com
Sat Nov 7 15:29:15 CET 2015
---
libavcodec/qsvenc.c | 114 +++++++++++++++++++++++++++++++++++++++++++++--
libavcodec/qsvenc.h | 2 +-
libavcodec/qsvenc_h264.c | 2 +-
3 files changed, 113 insertions(+), 5 deletions(-)
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index df1f777..0ee45f9 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -30,6 +30,7 @@
#include "libavutil/log.h"
#include "libavutil/time.h"
#include "libavutil/imgutils.h"
+#include "libavcodec/bytestream.h"
#include "avcodec.h"
#include "internal.h"
@@ -276,7 +277,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
q->param.AsyncDepth = q->async_depth;
q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
- (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
+ (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*) + sizeof(mfxEncodeCtrl*)));
if (!q->async_fifo)
return AVERROR(ENOMEM);
@@ -494,6 +495,27 @@ static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
}
}
+static void freep_encoder_ctrl(mfxEncodeCtrl** enc_ptr)
+{
+ mfxEncodeCtrl* enc_ctrl;
+
+ if (!enc_ptr)
+ return;
+
+ enc_ctrl = *enc_ptr;
+
+ if (enc_ctrl) {
+ int i;
+ for (i = 0; i < enc_ctrl->NumPayload; i++) {
+ av_free(enc_ctrl->Payload[i]->Data);
+ av_freep(&enc_ctrl->Payload[i]);
+ }
+ av_free(enc_ctrl->Payload);
+ av_freep(&enc_ctrl);
+ }
+ *enc_ptr = NULL;
+}
+
int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
AVPacket *pkt, const AVFrame *frame, int *got_packet)
{
@@ -504,6 +526,10 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
mfxSyncPoint sync = NULL;
int ret;
+ // for A53 CC data
+ mfxEncodeCtrl* enc_ctrl = NULL;
+ AVFrameSideData *side_data = NULL;
+
if (frame) {
ret = submit_frame(q, frame, &surf);
if (ret < 0) {
@@ -526,8 +552,83 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
bs->Data = new_pkt.data;
bs->MaxLength = new_pkt.size;
+ if (q->a53_cc && frame) {
+ side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC);
+ if (side_data) {
+
+ int sei_payload_size = 0;
+ mfxU8* sei_data = NULL;
+ mfxPayload* payload = NULL;
+ mfxPayload** payloads = NULL;
+
+ sei_payload_size = side_data->size + 13;
+
+ sei_data = av_mallocz(sei_payload_size);
+ if (!sei_data) {
+ av_log(avctx, AV_LOG_ERROR, "No memory for CC, skipping...\n");
+ goto skip_a53cc;
+ }
+
+ // SEI header
+ sei_data[0] = 4;
+ sei_data[1] = sei_payload_size - 2; // size of SEI data
+
+ // country code
+ sei_data[2] = 181;
+ sei_data[3] = 0;
+ sei_data[4] = 49;
+
+ // ATSC_identifier - using 'GA94' only
+ AV_WL32(sei_data + 5,
+ MKTAG('G', 'A', '9', '4'));
+ sei_data[9] = 3;
+ sei_data[10] =
+ ((side_data->size/3) & 0x1f) | 0xC0;
+
+ sei_data[11] = 0xFF; // reserved
+
+ memcpy(sei_data + 12, side_data->data, side_data->size);
+
+ sei_data[side_data->size+12] = 255;
+
+ payload = av_mallocz(sizeof(mfxPayload));
+ if (!payload) {
+ av_log(avctx, AV_LOG_ERROR, "No memory, skipping captions\n");
+ av_freep(&sei_data);
+ goto skip_a53cc;
+ }
+ payload->BufSize = side_data->size + 13;
+ payload->NumBit = payload->BufSize * 8;
+ payload->Type = 4;
+ payload->Data = sei_data;
+
+ payloads = av_mallocz(sizeof(mfxPayload*));
+ if (!payloads) {
+ av_log(avctx, AV_LOG_ERROR, "No memory, skipping captions\n");
+ av_freep(&sei_data);
+ av_freep(&payload);
+ goto skip_a53cc;
+ }
+
+ payloads[0] = payload;
+
+ enc_ctrl = av_mallocz(sizeof(mfxEncodeCtrl));
+ if (!enc_ctrl)
+ {
+ av_log(avctx, AV_LOG_VERBOSE, "No memory for mfxEncodeCtrl\n");
+ av_freep(&sei_data);
+ av_freep(&payload);
+ av_freep(&payloads);
+ goto skip_a53cc;
+ }
+ enc_ctrl->NumExtParam = 0;
+ enc_ctrl->NumPayload = 0;
+ enc_ctrl->Payload = payloads;
+ }
+ }
+skip_a53cc:
do {
- ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync);
+ ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, &sync);
if (ret == MFX_WRN_DEVICE_BUSY) {
av_usleep(500);
continue;
@@ -554,10 +655,12 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
if (sync) {
av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
- av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL);
+ av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL);
+ av_fifo_generic_write(q->async_fifo, &enc_ctrl,sizeof(mfxEncodeCtrl*),NULL);
} else {
av_packet_unref(&new_pkt);
av_freep(&bs);
+ freep_encoder_ctrl(&enc_ctrl);
}
if (!av_fifo_space(q->async_fifo) ||
@@ -565,6 +668,7 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
+ av_fifo_generic_read(q->async_fifo, &enc_ctrl,sizeof(mfxEncodeCtrl*),NULL);
MFXVideoCORE_SyncOperation(q->session, sync, 60000);
@@ -588,6 +692,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
#endif
av_freep(&bs);
+ freep_encoder_ctrl(&enc_ctrl);
if (pkt->data) {
if (pkt->size < new_pkt.size) {
@@ -635,13 +740,16 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
AVPacket pkt;
mfxSyncPoint sync;
mfxBitstream *bs;
+ mfxEncodeCtrl* enc_ctrl;
av_fifo_generic_read(q->async_fifo, &pkt, sizeof(pkt), NULL);
av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
+ av_fifo_generic_read(q->async_fifo, &enc_ctrl, sizeof(mfxEncodeCtrl*), NULL);
av_freep(&bs);
av_packet_unref(&pkt);
+ freep_encoder_ctrl(&enc_ctrl);
}
av_fifo_free(q->async_fifo);
q->async_fifo = NULL;
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 3dd7afe..d2fa6b4 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -76,7 +76,7 @@ typedef struct QSVEncContext {
int look_ahead;
int look_ahead_depth;
int look_ahead_downsampling;
-
+ int a53_cc;
char *load_plugins;
} QSVEncContext;
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 0e5a26c..5bdb5f4 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -97,7 +97,7 @@ static const AVOption options[] = {
{ "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_3 }, INT_MIN, INT_MAX, VE, "preset" },
{ "slower", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_2 }, INT_MIN, INT_MAX, VE, "preset" },
{ "veryslow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" },
-
+ {"a53cc", "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE},
{ NULL },
};
--
2.6.2
More information about the ffmpeg-devel
mailing list