--- 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel