summaryrefslogtreecommitdiffstats
path: root/libavcodec/qsvenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/qsvenc.c')
-rw-r--r--libavcodec/qsvenc.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 16d942f..74c273c 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -4,20 +4,20 @@
* copyright (c) 2013 Yukinori Yamazoe
* copyright (c) 2015 Anton Khirnov
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -32,6 +32,7 @@
#include "libavutil/log.h"
#include "libavutil/time.h"
#include "libavutil/imgutils.h"
+#include "libavcodec/bytestream.h"
#include "avcodec.h"
#include "internal.h"
@@ -135,9 +136,6 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
#if QSV_HAVE_CO2
mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
#endif
-#if QSV_HAVE_CO3
- mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
-#endif
av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
print_profile(info->CodecProfile), info->CodecLevel);
@@ -192,12 +190,6 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
info->ICQQuality, co2->LookAheadDepth);
}
#endif
-#if QSV_HAVE_QVBR
- else if (info->RateControlMethod == MFX_RATECONTROL_QVBR) {
- av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n",
- co3->QVBRQuality);
- }
-#endif
av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n",
info->NumSlice, info->NumRefFrame);
@@ -278,7 +270,7 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q)
const char *rc_desc;
mfxU16 rc_mode;
- int want_la = q->la_depth >= 10;
+ int want_la = q->look_ahead;
int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
int want_vcm = q->vcm;
@@ -541,11 +533,11 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
#if QSV_HAVE_LA
case MFX_RATECONTROL_LA:
q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
- q->extco2.LookAheadDepth = q->la_depth;
+ q->extco2.LookAheadDepth = q->look_ahead_depth;
break;
#if QSV_HAVE_ICQ
case MFX_RATECONTROL_LA_ICQ:
- q->extco2.LookAheadDepth = q->la_depth;
+ q->extco2.LookAheadDepth = q->look_ahead_depth;
case MFX_RATECONTROL_ICQ:
q->param.mfx.ICQQuality = avctx->global_quality;
break;
@@ -559,6 +551,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
q->extco.Header.BufferSz = sizeof(q->extco);
+ q->extco.PicTimingSEI = q->pic_timing_sei ?
+ MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
+
if (q->rdo >= 0)
q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
@@ -616,7 +611,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
#endif
#if QSV_HAVE_LA_DS
- q->extco2.LookAheadDS = q->la_ds;
+ q->extco2.LookAheadDS = q->look_ahead_downsampling;
#endif
#if QSV_HAVE_BREF_TYPE
@@ -691,12 +686,6 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
.Header.BufferSz = sizeof(co2),
};
#endif
-#if QSV_HAVE_CO3
- mfxExtCodingOption3 co3 = {
- .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3,
- .Header.BufferSz = sizeof(co3),
- };
-#endif
mfxExtBuffer *ext_buffers[] = {
(mfxExtBuffer*)&extradata,
@@ -704,9 +693,6 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
#if QSV_HAVE_CO2
(mfxExtBuffer*)&co2,
#endif
-#if QSV_HAVE_CO3
- (mfxExtBuffer*)&co3,
-#endif
};
int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
@@ -955,11 +941,23 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
return 0;
}
+static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl)
+{
+ if (enc_ctrl) {
+ int i;
+ for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) {
+ av_free(enc_ctrl->Payload[i]);
+ }
+ enc_ctrl->NumPayload = 0;
+ }
+}
+
static void clear_unused_frames(QSVEncContext *q)
{
QSVFrame *cur = q->work_frames;
while (cur) {
if (cur->used && !cur->surface.Data.Locked) {
+ free_encoder_ctrl_payloads(&cur->enc_ctrl);
av_frame_unref(cur->frame);
cur->used = 0;
}
@@ -994,6 +992,11 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f)
av_freep(&frame);
return AVERROR(ENOMEM);
}
+ frame->enc_ctrl.Payload = av_mallocz(sizeof(mfxPayload*) * QSV_MAX_ENC_PAYLOAD);
+ if (!frame->enc_ctrl.Payload) {
+ av_freep(&frame);
+ return AVERROR(ENOMEM);
+ }
*last = frame;
*f = frame;
@@ -1003,7 +1006,7 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f)
}
static int submit_frame(QSVEncContext *q, const AVFrame *frame,
- mfxFrameSurface1 **surface)
+ QSVFrame **new_frame)
{
QSVFrame *qf;
int ret;
@@ -1069,7 +1072,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame,
qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
- *surface = &qf->surface;
+ *new_frame = qf;
return 0;
}
@@ -1094,15 +1097,21 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
mfxFrameSurface1 *surf = NULL;
mfxSyncPoint *sync = NULL;
+ QSVFrame *qsv_frame = NULL;
+ mfxEncodeCtrl* enc_ctrl = NULL;
int ret;
if (frame) {
- ret = submit_frame(q, frame, &surf);
+ ret = submit_frame(q, frame, &qsv_frame);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
return ret;
}
}
+ if (qsv_frame) {
+ surf = &qsv_frame->surface;
+ enc_ctrl = &qsv_frame->enc_ctrl;
+ }
ret = av_new_packet(&new_pkt, q->packet_size);
if (ret < 0) {
@@ -1118,6 +1127,10 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
bs->Data = new_pkt.data;
bs->MaxLength = new_pkt.size;
+ if (q->set_encode_ctrl_cb) {
+ q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl);
+ }
+
sync = av_mallocz(sizeof(*sync));
if (!sync) {
av_freep(&bs);
@@ -1126,9 +1139,9 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
}
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(1);
+ av_usleep(500);
} while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION);
if (ret > 0)
@@ -1245,6 +1258,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
while (cur) {
q->work_frames = cur->next;
av_frame_free(&cur->frame);
+ av_free(cur->enc_ctrl.Payload);
av_freep(&cur);
cur = q->work_frames;
}
OpenPOWER on IntegriCloud