blob: 389335f39d260c571cd2db0457d8a84ab35003bf
1 | /* |
2 | * Intel MediaSDK QSV based H.264 enccoder |
3 | * |
4 | * copyright (c) 2013 Yukinori Yamazoe |
5 | * |
6 | * This file is part of FFmpeg. |
7 | * |
8 | * FFmpeg is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public |
10 | * License as published by the Free Software Foundation; either |
11 | * version 2.1 of the License, or (at your option) any later version. |
12 | * |
13 | * FFmpeg is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with FFmpeg; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | */ |
22 | |
23 | |
24 | #include <stdint.h> |
25 | #include <sys/types.h> |
26 | |
27 | #include <mfx/mfxvideo.h> |
28 | |
29 | #include "libavutil/common.h" |
30 | #include "libavutil/opt.h" |
31 | |
32 | #include "avcodec.h" |
33 | #include "internal.h" |
34 | #include "qsv.h" |
35 | #include "qsv_internal.h" |
36 | #include "qsvenc.h" |
37 | |
38 | typedef struct QSVH264EncContext { |
39 | AVClass *class; |
40 | QSVEncContext qsv; |
41 | } QSVH264EncContext; |
42 | |
43 | static int qsv_h264_set_encode_ctrl(AVCodecContext *avctx, |
44 | const AVFrame *frame, mfxEncodeCtrl* enc_ctrl) |
45 | { |
46 | QSVH264EncContext *qh264 = avctx->priv_data; |
47 | QSVEncContext *q = &qh264->qsv; |
48 | |
49 | if (q->a53_cc && frame) { |
50 | mfxPayload* payload; |
51 | mfxU8* sei_data; |
52 | size_t sei_size; |
53 | int res; |
54 | |
55 | res = ff_alloc_a53_sei(frame, sizeof(mfxPayload) + 2, (void**)&payload, &sei_size); |
56 | if (res < 0 || !payload) |
57 | return res; |
58 | |
59 | sei_data = (mfxU8*)(payload + 1); |
60 | // SEI header |
61 | sei_data[0] = 4; |
62 | sei_data[1] = (mfxU8)sei_size; // size of SEI data |
63 | // SEI data filled in by ff_alloc_a53_sei |
64 | |
65 | payload->BufSize = sei_size + 2; |
66 | payload->NumBit = payload->BufSize * 8; |
67 | payload->Type = 4; |
68 | payload->Data = sei_data; |
69 | |
70 | enc_ctrl->NumExtParam = 0; |
71 | enc_ctrl->NumPayload = 1; |
72 | enc_ctrl->Payload[0] = payload; |
73 | } |
74 | return 0; |
75 | } |
76 | |
77 | static av_cold int qsv_enc_init(AVCodecContext *avctx) |
78 | { |
79 | QSVH264EncContext *q = avctx->priv_data; |
80 | |
81 | q->qsv.set_encode_ctrl_cb = qsv_h264_set_encode_ctrl; |
82 | return ff_qsv_enc_init(avctx, &q->qsv); |
83 | } |
84 | |
85 | static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, |
86 | const AVFrame *frame, int *got_packet) |
87 | { |
88 | QSVH264EncContext *q = avctx->priv_data; |
89 | |
90 | return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); |
91 | } |
92 | |
93 | static av_cold int qsv_enc_close(AVCodecContext *avctx) |
94 | { |
95 | QSVH264EncContext *q = avctx->priv_data; |
96 | |
97 | return ff_qsv_enc_close(avctx, &q->qsv); |
98 | } |
99 | |
100 | #define OFFSET(x) offsetof(QSVH264EncContext, x) |
101 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
102 | static const AVOption options[] = { |
103 | QSV_COMMON_OPTS |
104 | |
105 | { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, |
106 | { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, |
107 | { "single_sei_nal_unit", "Put all the SEI messages into one NALU", OFFSET(qsv.single_sei_nal_unit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, |
108 | { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, |
109 | |
110 | #if QSV_HAVE_LA |
111 | { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, |
112 | { "look_ahead_depth", "Depth of look ahead in number frames", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE }, |
113 | #endif |
114 | #if QSV_HAVE_LA_DS |
115 | { "look_ahead_downsampling", NULL, OFFSET(qsv.look_ahead_downsampling), AV_OPT_TYPE_INT, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_2x, VE, "look_ahead_downsampling" }, |
116 | { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, |
117 | { "off" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, |
118 | { "2x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, |
119 | #endif |
120 | |
121 | { "int_ref_type", "Intra refresh type", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, |
122 | { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, |
123 | { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, |
124 | { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, |
125 | { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, |
126 | { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, |
127 | |
128 | { "trellis", "Trellis quantization", OFFSET(qsv.trellis), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, UINT_MAX, VE, "trellis" }, |
129 | { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_OFF }, .flags = VE, "trellis" }, |
130 | { "I", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_I }, .flags = VE, "trellis" }, |
131 | { "P", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_P }, .flags = VE, "trellis" }, |
132 | { "B", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_B }, .flags = VE, "trellis" }, |
133 | |
134 | { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, |
135 | { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, |
136 | { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, |
137 | { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, |
138 | { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, |
139 | |
140 | { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, VE}, |
141 | { NULL }, |
142 | }; |
143 | |
144 | static const AVClass class = { |
145 | .class_name = "h264_qsv encoder", |
146 | .item_name = av_default_item_name, |
147 | .option = options, |
148 | .version = LIBAVUTIL_VERSION_INT, |
149 | }; |
150 | |
151 | static const AVCodecDefault qsv_enc_defaults[] = { |
152 | { "b", "1M" }, |
153 | { "refs", "0" }, |
154 | // same as the x264 default |
155 | { "g", "250" }, |
156 | { "bf", "3" }, |
157 | { "coder", "ac" }, |
158 | |
159 | { "flags", "+cgop" }, |
160 | #if FF_API_PRIVATE_OPT |
161 | { "b_strategy", "-1" }, |
162 | #endif |
163 | { NULL }, |
164 | }; |
165 | |
166 | AVCodec ff_h264_qsv_encoder = { |
167 | .name = "h264_qsv", |
168 | .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), |
169 | .priv_data_size = sizeof(QSVH264EncContext), |
170 | .type = AVMEDIA_TYPE_VIDEO, |
171 | .id = AV_CODEC_ID_H264, |
172 | .init = qsv_enc_init, |
173 | .encode2 = qsv_enc_frame, |
174 | .close = qsv_enc_close, |
175 | .capabilities = AV_CODEC_CAP_DELAY, |
176 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, |
177 | AV_PIX_FMT_P010, |
178 | AV_PIX_FMT_QSV, |
179 | AV_PIX_FMT_NONE }, |
180 | .priv_class = &class, |
181 | .defaults = qsv_enc_defaults, |
182 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
183 | }; |
184 |