You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
10KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <va/va.h>
  19. #include <va/va_enc_vp9.h>
  20. #include "libavutil/avassert.h"
  21. #include "libavutil/common.h"
  22. #include "libavutil/internal.h"
  23. #include "libavutil/opt.h"
  24. #include "libavutil/pixfmt.h"
  25. #include "avcodec.h"
  26. #include "internal.h"
  27. #include "vaapi_encode.h"
  28. #define VP9_MAX_QUANT 255
  29. typedef struct VAAPIEncodeVP9Picture {
  30. int slot;
  31. } VAAPIEncodeVP9Picture;
  32. typedef struct VAAPIEncodeVP9Context {
  33. VAAPIEncodeContext common;
  34. // User options.
  35. int loop_filter_level;
  36. int loop_filter_sharpness;
  37. // Derived settings.
  38. int q_idx_idr;
  39. int q_idx_p;
  40. int q_idx_b;
  41. } VAAPIEncodeVP9Context;
  42. static int vaapi_encode_vp9_init_sequence_params(AVCodecContext *avctx)
  43. {
  44. VAAPIEncodeContext *ctx = avctx->priv_data;
  45. VAEncSequenceParameterBufferVP9 *vseq = ctx->codec_sequence_params;
  46. VAEncPictureParameterBufferVP9 *vpic = ctx->codec_picture_params;
  47. vseq->max_frame_width = avctx->width;
  48. vseq->max_frame_height = avctx->height;
  49. vseq->kf_auto = 0;
  50. if (!(ctx->va_rc_mode & VA_RC_CQP)) {
  51. vseq->bits_per_second = ctx->va_bit_rate;
  52. vseq->intra_period = ctx->gop_size;
  53. }
  54. vpic->frame_width_src = avctx->width;
  55. vpic->frame_height_src = avctx->height;
  56. vpic->frame_width_dst = avctx->width;
  57. vpic->frame_height_dst = avctx->height;
  58. return 0;
  59. }
  60. static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx,
  61. VAAPIEncodePicture *pic)
  62. {
  63. VAAPIEncodeContext *ctx = avctx->priv_data;
  64. VAAPIEncodeVP9Context *priv = avctx->priv_data;
  65. VAAPIEncodeVP9Picture *hpic = pic->priv_data;
  66. VAEncPictureParameterBufferVP9 *vpic = pic->codec_picture_params;
  67. int i;
  68. vpic->reconstructed_frame = pic->recon_surface;
  69. vpic->coded_buf = pic->output_buffer;
  70. switch (pic->type) {
  71. case PICTURE_TYPE_IDR:
  72. av_assert0(pic->nb_refs == 0);
  73. vpic->ref_flags.bits.force_kf = 1;
  74. vpic->refresh_frame_flags = 0xff;
  75. hpic->slot = 0;
  76. break;
  77. case PICTURE_TYPE_P:
  78. av_assert0(pic->nb_refs == 1);
  79. {
  80. VAAPIEncodeVP9Picture *href = pic->refs[0]->priv_data;
  81. av_assert0(href->slot == 0 || href->slot == 1);
  82. if (ctx->max_b_depth > 0) {
  83. hpic->slot = !href->slot;
  84. vpic->refresh_frame_flags = 1 << hpic->slot | 0xfc;
  85. } else {
  86. hpic->slot = 0;
  87. vpic->refresh_frame_flags = 0xff;
  88. }
  89. vpic->ref_flags.bits.ref_frame_ctrl_l0 = 1;
  90. vpic->ref_flags.bits.ref_last_idx = href->slot;
  91. vpic->ref_flags.bits.ref_last_sign_bias = 1;
  92. }
  93. break;
  94. case PICTURE_TYPE_B:
  95. av_assert0(pic->nb_refs == 2);
  96. {
  97. VAAPIEncodeVP9Picture *href0 = pic->refs[0]->priv_data,
  98. *href1 = pic->refs[1]->priv_data;
  99. av_assert0(href0->slot < pic->b_depth + 1 &&
  100. href1->slot < pic->b_depth + 1);
  101. if (pic->b_depth == ctx->max_b_depth) {
  102. // Unreferenced frame.
  103. vpic->refresh_frame_flags = 0x00;
  104. hpic->slot = 8;
  105. } else {
  106. vpic->refresh_frame_flags = 0xfe << pic->b_depth & 0xff;
  107. hpic->slot = 1 + pic->b_depth;
  108. }
  109. vpic->ref_flags.bits.ref_frame_ctrl_l0 = 1;
  110. vpic->ref_flags.bits.ref_frame_ctrl_l1 = 2;
  111. vpic->ref_flags.bits.ref_last_idx = href0->slot;
  112. vpic->ref_flags.bits.ref_last_sign_bias = 1;
  113. vpic->ref_flags.bits.ref_gf_idx = href1->slot;
  114. vpic->ref_flags.bits.ref_gf_sign_bias = 0;
  115. }
  116. break;
  117. default:
  118. av_assert0(0 && "invalid picture type");
  119. }
  120. if (vpic->refresh_frame_flags == 0x00) {
  121. av_log(avctx, AV_LOG_DEBUG, "Pic %"PRId64" not stored.\n",
  122. pic->display_order);
  123. } else {
  124. av_log(avctx, AV_LOG_DEBUG, "Pic %"PRId64" stored in slot %d.\n",
  125. pic->display_order, hpic->slot);
  126. }
  127. for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++)
  128. vpic->reference_frames[i] = VA_INVALID_SURFACE;
  129. for (i = 0; i < pic->nb_refs; i++) {
  130. VAAPIEncodePicture *ref_pic = pic->refs[i];
  131. int slot;
  132. slot = ((VAAPIEncodeVP9Picture*)ref_pic->priv_data)->slot;
  133. av_assert0(vpic->reference_frames[slot] == VA_INVALID_SURFACE);
  134. vpic->reference_frames[slot] = ref_pic->recon_surface;
  135. }
  136. vpic->pic_flags.bits.frame_type = (pic->type != PICTURE_TYPE_IDR);
  137. vpic->pic_flags.bits.show_frame = pic->display_order <= pic->encode_order;
  138. if (pic->type == PICTURE_TYPE_IDR)
  139. vpic->luma_ac_qindex = priv->q_idx_idr;
  140. else if (pic->type == PICTURE_TYPE_P)
  141. vpic->luma_ac_qindex = priv->q_idx_p;
  142. else
  143. vpic->luma_ac_qindex = priv->q_idx_b;
  144. vpic->luma_dc_qindex_delta = 0;
  145. vpic->chroma_ac_qindex_delta = 0;
  146. vpic->chroma_dc_qindex_delta = 0;
  147. vpic->filter_level = priv->loop_filter_level;
  148. vpic->sharpness_level = priv->loop_filter_sharpness;
  149. return 0;
  150. }
  151. static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx)
  152. {
  153. VAAPIEncodeContext *ctx = avctx->priv_data;
  154. VAAPIEncodeVP9Context *priv = avctx->priv_data;
  155. if (ctx->rc_mode->quality) {
  156. priv->q_idx_p = av_clip(ctx->rc_quality, 0, VP9_MAX_QUANT);
  157. if (avctx->i_quant_factor > 0.0)
  158. priv->q_idx_idr =
  159. av_clip((avctx->i_quant_factor * priv->q_idx_p +
  160. avctx->i_quant_offset) + 0.5,
  161. 0, VP9_MAX_QUANT);
  162. else
  163. priv->q_idx_idr = priv->q_idx_p;
  164. if (avctx->b_quant_factor > 0.0)
  165. priv->q_idx_b =
  166. av_clip((avctx->b_quant_factor * priv->q_idx_p +
  167. avctx->b_quant_offset) + 0.5,
  168. 0, VP9_MAX_QUANT);
  169. else
  170. priv->q_idx_b = priv->q_idx_p;
  171. } else {
  172. // Arbitrary value.
  173. priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 100;
  174. }
  175. ctx->roi_quant_range = VP9_MAX_QUANT;
  176. return 0;
  177. }
  178. static const VAAPIEncodeProfile vaapi_encode_vp9_profiles[] = {
  179. { FF_PROFILE_VP9_0, 8, 3, 1, 1, VAProfileVP9Profile0 },
  180. { FF_PROFILE_VP9_2, 10, 3, 1, 1, VAProfileVP9Profile2 },
  181. { FF_PROFILE_UNKNOWN }
  182. };
  183. static const VAAPIEncodeType vaapi_encode_type_vp9 = {
  184. .profiles = vaapi_encode_vp9_profiles,
  185. .flags = FLAG_B_PICTURES |
  186. FLAG_B_PICTURE_REFERENCES,
  187. .default_quality = 100,
  188. .picture_priv_data_size = sizeof(VAAPIEncodeVP9Picture),
  189. .configure = &vaapi_encode_vp9_configure,
  190. .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9),
  191. .init_sequence_params = &vaapi_encode_vp9_init_sequence_params,
  192. .picture_params_size = sizeof(VAEncPictureParameterBufferVP9),
  193. .init_picture_params = &vaapi_encode_vp9_init_picture_params,
  194. };
  195. static av_cold int vaapi_encode_vp9_init(AVCodecContext *avctx)
  196. {
  197. VAAPIEncodeContext *ctx = avctx->priv_data;
  198. ctx->codec = &vaapi_encode_type_vp9;
  199. // No packed headers are currently desired. They could be written,
  200. // but there isn't any reason to do so - the one usable driver (i965)
  201. // can write its own headers and there is no metadata to include.
  202. ctx->desired_packed_headers = 0;
  203. // Surfaces must be aligned to superblock boundaries.
  204. ctx->surface_width = FFALIGN(avctx->width, 64);
  205. ctx->surface_height = FFALIGN(avctx->height, 64);
  206. return ff_vaapi_encode_init(avctx);
  207. }
  208. #define OFFSET(x) offsetof(VAAPIEncodeVP9Context, x)
  209. #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
  210. static const AVOption vaapi_encode_vp9_options[] = {
  211. VAAPI_ENCODE_COMMON_OPTIONS,
  212. VAAPI_ENCODE_RC_OPTIONS,
  213. { "loop_filter_level", "Loop filter level",
  214. OFFSET(loop_filter_level), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, 63, FLAGS },
  215. { "loop_filter_sharpness", "Loop filter sharpness",
  216. OFFSET(loop_filter_sharpness), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 15, FLAGS },
  217. { NULL },
  218. };
  219. static const AVCodecDefault vaapi_encode_vp9_defaults[] = {
  220. { "b", "0" },
  221. { "bf", "0" },
  222. { "g", "250" },
  223. { "qmin", "-1" },
  224. { "qmax", "-1" },
  225. { NULL },
  226. };
  227. static const AVClass vaapi_encode_vp9_class = {
  228. .class_name = "vp9_vaapi",
  229. .item_name = av_default_item_name,
  230. .option = vaapi_encode_vp9_options,
  231. .version = LIBAVUTIL_VERSION_INT,
  232. };
  233. AVCodec ff_vp9_vaapi_encoder = {
  234. .name = "vp9_vaapi",
  235. .long_name = NULL_IF_CONFIG_SMALL("VP9 (VAAPI)"),
  236. .type = AVMEDIA_TYPE_VIDEO,
  237. .id = AV_CODEC_ID_VP9,
  238. .priv_data_size = sizeof(VAAPIEncodeVP9Context),
  239. .init = &vaapi_encode_vp9_init,
  240. .send_frame = &ff_vaapi_encode_send_frame,
  241. .receive_packet = &ff_vaapi_encode_receive_packet,
  242. .close = &ff_vaapi_encode_close,
  243. .priv_class = &vaapi_encode_vp9_class,
  244. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
  245. .defaults = vaapi_encode_vp9_defaults,
  246. .pix_fmts = (const enum AVPixelFormat[]) {
  247. AV_PIX_FMT_VAAPI,
  248. AV_PIX_FMT_NONE,
  249. },
  250. .wrapper_name = "vaapi",
  251. };