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 19#include <va/va.h> 20#include <va/va_enc_mpeg2.h> 21 22#include "libavutil/avassert.h" 23#include "libavutil/opt.h" 24 25#include "avcodec.h" 26#include "cbs.h" 27#include "cbs_mpeg2.h" 28#include "codec_internal.h" 29#include "mpeg12.h" 30#include "vaapi_encode.h" 31 32typedef struct VAAPIEncodeMPEG2Context { 33 VAAPIEncodeContext common; 34 35 // User options. 36 int profile; 37 int level; 38 39 // Derived settings. 40 int quant_i; 41 int quant_p; 42 int quant_b; 43 44 unsigned int bit_rate; 45 unsigned int vbv_buffer_size; 46 47 AVRational frame_rate; 48 49 unsigned int f_code_horizontal; 50 unsigned int f_code_vertical; 51 52 // Stream state. 53 int64_t last_i_frame; 54 55 // Writer structures. 56 MPEG2RawSequenceHeader sequence_header; 57 MPEG2RawExtensionData sequence_extension; 58 MPEG2RawExtensionData sequence_display_extension; 59 MPEG2RawGroupOfPicturesHeader gop_header; 60 MPEG2RawPictureHeader picture_header; 61 MPEG2RawExtensionData picture_coding_extension; 62 63 CodedBitstreamContext *cbc; 64 CodedBitstreamFragment current_fragment; 65} VAAPIEncodeMPEG2Context; 66 67 68static int vaapi_encode_mpeg2_write_fragment(AVCodecContext *avctx, 69 char *data, size_t *data_len, 70 CodedBitstreamFragment *frag) 71{ 72 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 73 int err; 74 75 err = ff_cbs_write_fragment_data(priv->cbc, frag); 76 if (err < 0) { 77 av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); 78 return err; 79 } 80 81 if (*data_len < 8 * frag->data_size - frag->data_bit_padding) { 82 av_log(avctx, AV_LOG_ERROR, "Access unit too large: " 83 "%zu < %zu.\n", *data_len, 84 8 * frag->data_size - frag->data_bit_padding); 85 return AVERROR(ENOSPC); 86 } 87 88 memcpy(data, frag->data, frag->data_size); 89 *data_len = 8 * frag->data_size - frag->data_bit_padding; 90 91 return 0; 92} 93 94static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, 95 CodedBitstreamFragment *frag, 96 int type, void *header) 97{ 98 int err; 99 100 err = ff_cbs_insert_unit_content(frag, -1, type, header, NULL); 101 if (err < 0) { 102 av_log(avctx, AV_LOG_ERROR, "Failed to add header: " 103 "type = %d.\n", type); 104 return err; 105 } 106 107 return 0; 108} 109 110static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, 111 char *data, size_t *data_len) 112{ 113 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 114 CodedBitstreamFragment *frag = &priv->current_fragment; 115 int err; 116 117 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_SEQUENCE_HEADER, 118 &priv->sequence_header); 119 if (err < 0) 120 goto fail; 121 122 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, 123 &priv->sequence_extension); 124 if (err < 0) 125 goto fail; 126 127 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, 128 &priv->sequence_display_extension); 129 if (err < 0) 130 goto fail; 131 132 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_GROUP, 133 &priv->gop_header); 134 if (err < 0) 135 goto fail; 136 137 err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); 138fail: 139 ff_cbs_fragment_reset(frag); 140 return 0; 141} 142 143static int vaapi_encode_mpeg2_write_picture_header(AVCodecContext *avctx, 144 VAAPIEncodePicture *pic, 145 char *data, size_t *data_len) 146{ 147 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 148 CodedBitstreamFragment *frag = &priv->current_fragment; 149 int err; 150 151 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_PICTURE, 152 &priv->picture_header); 153 if (err < 0) 154 goto fail; 155 156 err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, 157 &priv->picture_coding_extension); 158 if (err < 0) 159 goto fail; 160 161 err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); 162fail: 163 ff_cbs_fragment_reset(frag); 164 return 0; 165} 166 167static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) 168{ 169 VAAPIEncodeContext *ctx = avctx->priv_data; 170 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 171 MPEG2RawSequenceHeader *sh = &priv->sequence_header; 172 MPEG2RawSequenceExtension *se = &priv->sequence_extension.data.sequence; 173 MPEG2RawSequenceDisplayExtension *sde = &priv->sequence_display_extension.data.sequence_display; 174 MPEG2RawGroupOfPicturesHeader *goph = &priv->gop_header; 175 MPEG2RawPictureHeader *ph = &priv->picture_header; 176 MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; 177 VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; 178 VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; 179 int code, ext_n, ext_d; 180 181 memset(sh, 0, sizeof(*sh)); 182 memset(se, 0, sizeof(*se)); 183 memset(sde, 0, sizeof(*sde)); 184 memset(goph, 0, sizeof(*goph)); 185 memset(ph, 0, sizeof(*ph)); 186 memset(pce, 0, sizeof(*pce)); 187 188 189 if (ctx->va_bit_rate > 0) { 190 priv->bit_rate = (ctx->va_bit_rate + 399) / 400; 191 } else { 192 // Unknown (not a bitrate-targetting mode), so just use the 193 // highest value. 194 priv->bit_rate = 0x3fffffff; 195 } 196 if (avctx->rc_buffer_size > 0) { 197 priv->vbv_buffer_size = (avctx->rc_buffer_size + (1 << 14) - 1) >> 14; 198 } else { 199 // Unknown, so guess a value from the bitrate. 200 priv->vbv_buffer_size = priv->bit_rate >> 14; 201 } 202 203 switch (avctx->level) { 204 case 4: // High. 205 case 6: // High 1440. 206 priv->f_code_horizontal = 9; 207 priv->f_code_vertical = 5; 208 break; 209 case 8: // Main. 210 priv->f_code_horizontal = 8; 211 priv->f_code_vertical = 5; 212 break; 213 case 10: // Low. 214 default: 215 priv->f_code_horizontal = 7; 216 priv->f_code_vertical = 4; 217 break; 218 } 219 220 221 // Sequence header 222 223 sh->sequence_header_code = MPEG2_START_SEQUENCE_HEADER; 224 225 sh->horizontal_size_value = avctx->width & 0xfff; 226 sh->vertical_size_value = avctx->height & 0xfff; 227 228 if (avctx->sample_aspect_ratio.num != 0 && 229 avctx->sample_aspect_ratio.den != 0) { 230 AVRational dar = av_div_q(avctx->sample_aspect_ratio, 231 (AVRational) { avctx->width, avctx->height }); 232 233 if (av_cmp_q(avctx->sample_aspect_ratio, (AVRational) { 1, 1 }) == 0) { 234 sh->aspect_ratio_information = 1; 235 } else if (av_cmp_q(dar, (AVRational) { 3, 4 }) == 0) { 236 sh->aspect_ratio_information = 2; 237 } else if (av_cmp_q(dar, (AVRational) { 9, 16 }) == 0) { 238 sh->aspect_ratio_information = 3; 239 } else if (av_cmp_q(dar, (AVRational) { 100, 221 }) == 0) { 240 sh->aspect_ratio_information = 4; 241 } else { 242 av_log(avctx, AV_LOG_WARNING, "Sample aspect ratio %d:%d is not " 243 "representable, signalling square pixels instead.\n", 244 avctx->sample_aspect_ratio.num, 245 avctx->sample_aspect_ratio.den); 246 sh->aspect_ratio_information = 1; 247 } 248 } else { 249 // Unknown - assume square pixels. 250 sh->aspect_ratio_information = 1; 251 } 252 253 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) 254 priv->frame_rate = avctx->framerate; 255 else 256 priv->frame_rate = av_inv_q(avctx->time_base); 257 ff_mpeg12_find_best_frame_rate(priv->frame_rate, 258 &code, &ext_n, &ext_d, 0); 259 sh->frame_rate_code = code; 260 261 sh->bit_rate_value = priv->bit_rate & 0x3ffff; 262 sh->vbv_buffer_size_value = priv->vbv_buffer_size & 0x3ff; 263 264 sh->constrained_parameters_flag = 0; 265 sh->load_intra_quantiser_matrix = 0; 266 sh->load_non_intra_quantiser_matrix = 0; 267 268 269 // Sequence extension 270 271 priv->sequence_extension.extension_start_code = MPEG2_START_EXTENSION; 272 priv->sequence_extension.extension_start_code_identifier = 273 MPEG2_EXTENSION_SEQUENCE; 274 275 se->profile_and_level_indication = avctx->profile << 4 | avctx->level; 276 se->progressive_sequence = 1; 277 se->chroma_format = 1; 278 279 se->horizontal_size_extension = avctx->width >> 12; 280 se->vertical_size_extension = avctx->height >> 12; 281 282 se->bit_rate_extension = priv->bit_rate >> 18; 283 se->vbv_buffer_size_extension = priv->vbv_buffer_size >> 10; 284 se->low_delay = ctx->b_per_p == 0; 285 286 se->frame_rate_extension_n = ext_n; 287 se->frame_rate_extension_d = ext_d; 288 289 290 // Sequence display extension 291 292 priv->sequence_display_extension.extension_start_code = 293 MPEG2_START_EXTENSION; 294 priv->sequence_display_extension.extension_start_code_identifier = 295 MPEG2_EXTENSION_SEQUENCE_DISPLAY; 296 297 // Unspecified video format, from table 6-6. 298 sde->video_format = 5; 299 300 sde->colour_primaries = avctx->color_primaries; 301 sde->transfer_characteristics = avctx->color_trc; 302 sde->matrix_coefficients = avctx->colorspace; 303 sde->colour_description = 304 avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || 305 avctx->color_trc != AVCOL_TRC_UNSPECIFIED || 306 avctx->colorspace != AVCOL_SPC_UNSPECIFIED; 307 308 sde->display_horizontal_size = avctx->width; 309 sde->display_vertical_size = avctx->height; 310 311 312 // GOP header 313 314 goph->group_start_code = MPEG2_START_GROUP; 315 316 // Marker bit in the middle of time_code. 317 goph->time_code = 1 << 12; 318 goph->closed_gop = 1; 319 goph->broken_link = 0; 320 321 322 // Defaults for picture header 323 324 ph->picture_start_code = MPEG2_START_PICTURE; 325 326 ph->vbv_delay = 0xffff; // Not currently calculated. 327 328 ph->full_pel_forward_vector = 0; 329 ph->forward_f_code = 7; 330 ph->full_pel_backward_vector = 0; 331 ph->forward_f_code = 7; 332 333 334 // Defaults for picture coding extension 335 336 priv->picture_coding_extension.extension_start_code = 337 MPEG2_START_EXTENSION; 338 priv->picture_coding_extension.extension_start_code_identifier = 339 MPEG2_EXTENSION_PICTURE_CODING; 340 341 pce->intra_dc_precision = 0; 342 pce->picture_structure = 3; 343 pce->top_field_first = 0; 344 pce->frame_pred_frame_dct = 1; 345 pce->concealment_motion_vectors = 0; 346 pce->q_scale_type = 0; 347 pce->intra_vlc_format = 0; 348 pce->alternate_scan = 0; 349 pce->repeat_first_field = 0; 350 pce->progressive_frame = 1; 351 pce->composite_display_flag = 0; 352 353 354 355 *vseq = (VAEncSequenceParameterBufferMPEG2) { 356 .intra_period = ctx->gop_size, 357 .ip_period = ctx->b_per_p + 1, 358 359 .picture_width = avctx->width, 360 .picture_height = avctx->height, 361 362 .bits_per_second = ctx->va_bit_rate, 363 .frame_rate = av_q2d(priv->frame_rate), 364 .aspect_ratio_information = sh->aspect_ratio_information, 365 .vbv_buffer_size = priv->vbv_buffer_size, 366 367 .sequence_extension.bits = { 368 .profile_and_level_indication = se->profile_and_level_indication, 369 .progressive_sequence = se->progressive_sequence, 370 .chroma_format = se->chroma_format, 371 .low_delay = se->low_delay, 372 .frame_rate_extension_n = se->frame_rate_extension_n, 373 .frame_rate_extension_d = se->frame_rate_extension_d, 374 }, 375 376 .new_gop_header = 1, 377 .gop_header.bits = { 378 .time_code = goph->time_code, 379 .closed_gop = goph->closed_gop, 380 .broken_link = goph->broken_link, 381 }, 382 }; 383 384 *vpic = (VAEncPictureParameterBufferMPEG2) { 385 .forward_reference_picture = VA_INVALID_ID, 386 .backward_reference_picture = VA_INVALID_ID, 387 .reconstructed_picture = VA_INVALID_ID, 388 .coded_buf = VA_INVALID_ID, 389 390 .vbv_delay = 0xffff, 391 .f_code = { { 15, 15 }, { 15, 15 } }, 392 393 .picture_coding_extension.bits = { 394 .intra_dc_precision = pce->intra_dc_precision, 395 .picture_structure = pce->picture_structure, 396 .top_field_first = pce->top_field_first, 397 .frame_pred_frame_dct = pce->frame_pred_frame_dct, 398 .concealment_motion_vectors = pce->concealment_motion_vectors, 399 .q_scale_type = pce->q_scale_type, 400 .intra_vlc_format = pce->intra_vlc_format, 401 .alternate_scan = pce->alternate_scan, 402 .repeat_first_field = pce->repeat_first_field, 403 .progressive_frame = pce->progressive_frame, 404 .composite_display_flag = pce->composite_display_flag, 405 }, 406 407 .composite_display.bits = { 408 .v_axis = pce->v_axis, 409 .field_sequence = pce->field_sequence, 410 .sub_carrier = pce->sub_carrier, 411 .burst_amplitude = pce->burst_amplitude, 412 .sub_carrier_phase = pce->sub_carrier_phase, 413 }, 414 }; 415 416 return 0; 417} 418 419static int vaapi_encode_mpeg2_init_picture_params(AVCodecContext *avctx, 420 VAAPIEncodePicture *pic) 421{ 422 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 423 MPEG2RawPictureHeader *ph = &priv->picture_header; 424 MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; 425 VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; 426 427 if (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I) { 428 ph->temporal_reference = 0; 429 ph->picture_coding_type = 1; 430 priv->last_i_frame = pic->display_order; 431 } else { 432 ph->temporal_reference = pic->display_order - priv->last_i_frame; 433 ph->picture_coding_type = pic->type == PICTURE_TYPE_B ? 3 : 2; 434 } 435 436 if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) { 437 pce->f_code[0][0] = priv->f_code_horizontal; 438 pce->f_code[0][1] = priv->f_code_vertical; 439 } else { 440 pce->f_code[0][0] = 15; 441 pce->f_code[0][1] = 15; 442 } 443 if (pic->type == PICTURE_TYPE_B) { 444 pce->f_code[1][0] = priv->f_code_horizontal; 445 pce->f_code[1][1] = priv->f_code_vertical; 446 } else { 447 pce->f_code[1][0] = 15; 448 pce->f_code[1][1] = 15; 449 } 450 451 vpic->reconstructed_picture = pic->recon_surface; 452 vpic->coded_buf = pic->output_buffer; 453 454 switch (pic->type) { 455 case PICTURE_TYPE_IDR: 456 case PICTURE_TYPE_I: 457 vpic->picture_type = VAEncPictureTypeIntra; 458 break; 459 case PICTURE_TYPE_P: 460 vpic->picture_type = VAEncPictureTypePredictive; 461 vpic->forward_reference_picture = pic->refs[0]->recon_surface; 462 break; 463 case PICTURE_TYPE_B: 464 vpic->picture_type = VAEncPictureTypeBidirectional; 465 vpic->forward_reference_picture = pic->refs[0]->recon_surface; 466 vpic->backward_reference_picture = pic->refs[1]->recon_surface; 467 break; 468 default: 469 av_assert0(0 && "invalid picture type"); 470 } 471 472 vpic->temporal_reference = ph->temporal_reference; 473 vpic->f_code[0][0] = pce->f_code[0][0]; 474 vpic->f_code[0][1] = pce->f_code[0][1]; 475 vpic->f_code[1][0] = pce->f_code[1][0]; 476 vpic->f_code[1][1] = pce->f_code[1][1]; 477 478 return 0; 479} 480 481static int vaapi_encode_mpeg2_init_slice_params(AVCodecContext *avctx, 482 VAAPIEncodePicture *pic, 483 VAAPIEncodeSlice *slice) 484{ 485 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 486 VAEncSliceParameterBufferMPEG2 *vslice = slice->codec_slice_params; 487 int qp; 488 489 vslice->macroblock_address = slice->block_start; 490 vslice->num_macroblocks = slice->block_size; 491 492 switch (pic->type) { 493 case PICTURE_TYPE_IDR: 494 case PICTURE_TYPE_I: 495 qp = priv->quant_i; 496 break; 497 case PICTURE_TYPE_P: 498 qp = priv->quant_p; 499 break; 500 case PICTURE_TYPE_B: 501 qp = priv->quant_b; 502 break; 503 default: 504 av_assert0(0 && "invalid picture type"); 505 } 506 507 vslice->quantiser_scale_code = qp; 508 vslice->is_intra_slice = (pic->type == PICTURE_TYPE_IDR || 509 pic->type == PICTURE_TYPE_I); 510 511 return 0; 512} 513 514static av_cold int vaapi_encode_mpeg2_configure(AVCodecContext *avctx) 515{ 516 VAAPIEncodeContext *ctx = avctx->priv_data; 517 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 518 int err; 519 520 err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_MPEG2VIDEO, avctx); 521 if (err < 0) 522 return err; 523 524 if (ctx->va_rc_mode == VA_RC_CQP) { 525 priv->quant_p = av_clip(ctx->rc_quality, 1, 31); 526 if (avctx->i_quant_factor > 0.0) 527 priv->quant_i = 528 av_clip((avctx->i_quant_factor * priv->quant_p + 529 avctx->i_quant_offset) + 0.5, 1, 31); 530 else 531 priv->quant_i = priv->quant_p; 532 if (avctx->b_quant_factor > 0.0) 533 priv->quant_b = 534 av_clip((avctx->b_quant_factor * priv->quant_p + 535 avctx->b_quant_offset) + 0.5, 1, 31); 536 else 537 priv->quant_b = priv->quant_p; 538 539 av_log(avctx, AV_LOG_DEBUG, "Using fixed quantiser " 540 "%d / %d / %d for I- / P- / B-frames.\n", 541 priv->quant_i, priv->quant_p, priv->quant_b); 542 543 } else { 544 priv->quant_i = 16; 545 priv->quant_p = 16; 546 priv->quant_b = 16; 547 } 548 549 ctx->slice_block_rows = FFALIGN(avctx->height, 16) / 16; 550 ctx->slice_block_cols = FFALIGN(avctx->width, 16) / 16; 551 552 ctx->nb_slices = ctx->slice_block_rows; 553 ctx->slice_size = 1; 554 555 ctx->roi_quant_range = 31; 556 557 return 0; 558} 559 560static const VAAPIEncodeProfile vaapi_encode_mpeg2_profiles[] = { 561 { FF_PROFILE_MPEG2_MAIN, 8, 3, 1, 1, VAProfileMPEG2Main }, 562 { FF_PROFILE_MPEG2_SIMPLE, 8, 3, 1, 1, VAProfileMPEG2Simple }, 563 { FF_PROFILE_UNKNOWN } 564}; 565 566static const VAAPIEncodeType vaapi_encode_type_mpeg2 = { 567 .profiles = vaapi_encode_mpeg2_profiles, 568 569 .flags = FLAG_B_PICTURES, 570 571 .configure = &vaapi_encode_mpeg2_configure, 572 573 .default_quality = 10, 574 575 .sequence_params_size = sizeof(VAEncSequenceParameterBufferMPEG2), 576 .init_sequence_params = &vaapi_encode_mpeg2_init_sequence_params, 577 578 .picture_params_size = sizeof(VAEncPictureParameterBufferMPEG2), 579 .init_picture_params = &vaapi_encode_mpeg2_init_picture_params, 580 581 .slice_params_size = sizeof(VAEncSliceParameterBufferMPEG2), 582 .init_slice_params = &vaapi_encode_mpeg2_init_slice_params, 583 584 .sequence_header_type = VAEncPackedHeaderSequence, 585 .write_sequence_header = &vaapi_encode_mpeg2_write_sequence_header, 586 587 .picture_header_type = VAEncPackedHeaderPicture, 588 .write_picture_header = &vaapi_encode_mpeg2_write_picture_header, 589}; 590 591static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) 592{ 593 VAAPIEncodeContext *ctx = avctx->priv_data; 594 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 595 596 ctx->codec = &vaapi_encode_type_mpeg2; 597 598 if (avctx->profile == FF_PROFILE_UNKNOWN) 599 avctx->profile = priv->profile; 600 if (avctx->level == FF_LEVEL_UNKNOWN) 601 avctx->level = priv->level; 602 603 // Reject unknown levels (these are required to set f_code for 604 // motion vector encoding). 605 switch (avctx->level) { 606 case 4: // High 607 case 6: // High 1440 608 case 8: // Main 609 case 10: // Low 610 break; 611 default: 612 av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 level %d.\n", 613 avctx->level); 614 return AVERROR(EINVAL); 615 } 616 617 if (avctx->height % 4096 == 0 || avctx->width % 4096 == 0) { 618 av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support picture " 619 "height or width divisible by 4096.\n"); 620 return AVERROR(EINVAL); 621 } 622 623 ctx->desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE | 624 VA_ENC_PACKED_HEADER_PICTURE; 625 626 return ff_vaapi_encode_init(avctx); 627} 628 629static av_cold int vaapi_encode_mpeg2_close(AVCodecContext *avctx) 630{ 631 VAAPIEncodeMPEG2Context *priv = avctx->priv_data; 632 633 ff_cbs_fragment_free(&priv->current_fragment); 634 ff_cbs_close(&priv->cbc); 635 636 return ff_vaapi_encode_close(avctx); 637} 638 639#define OFFSET(x) offsetof(VAAPIEncodeMPEG2Context, x) 640#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) 641static const AVOption vaapi_encode_mpeg2_options[] = { 642 VAAPI_ENCODE_COMMON_OPTIONS, 643 VAAPI_ENCODE_RC_OPTIONS, 644 645 { "profile", "Set profile (in profile_and_level_indication)", 646 OFFSET(profile), AV_OPT_TYPE_INT, 647 { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 7, FLAGS, "profile" }, 648 649#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ 650 { .i64 = value }, 0, 0, FLAGS, "profile" 651 { PROFILE("simple", FF_PROFILE_MPEG2_SIMPLE) }, 652 { PROFILE("main", FF_PROFILE_MPEG2_MAIN) }, 653#undef PROFILE 654 655 { "level", "Set level (in profile_and_level_indication)", 656 OFFSET(level), AV_OPT_TYPE_INT, 657 { .i64 = 4 }, 0, 15, FLAGS, "level" }, 658 659#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ 660 { .i64 = value }, 0, 0, FLAGS, "level" 661 { LEVEL("low", 10) }, 662 { LEVEL("main", 8) }, 663 { LEVEL("high_1440", 6) }, 664 { LEVEL("high", 4) }, 665#undef LEVEL 666 667 { NULL }, 668}; 669 670static const FFCodecDefault vaapi_encode_mpeg2_defaults[] = { 671 { "b", "0" }, 672 { "bf", "1" }, 673 { "g", "120" }, 674 { "i_qfactor", "1" }, 675 { "i_qoffset", "0" }, 676 { "b_qfactor", "6/5" }, 677 { "b_qoffset", "0" }, 678 { "qmin", "-1" }, 679 { "qmax", "-1" }, 680 { NULL }, 681}; 682 683static const AVClass vaapi_encode_mpeg2_class = { 684 .class_name = "mpeg2_vaapi", 685 .item_name = av_default_item_name, 686 .option = vaapi_encode_mpeg2_options, 687 .version = LIBAVUTIL_VERSION_INT, 688}; 689 690const FFCodec ff_mpeg2_vaapi_encoder = { 691 .p.name = "mpeg2_vaapi", 692 .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 (VAAPI)"), 693 .p.type = AVMEDIA_TYPE_VIDEO, 694 .p.id = AV_CODEC_ID_MPEG2VIDEO, 695 .priv_data_size = sizeof(VAAPIEncodeMPEG2Context), 696 .init = &vaapi_encode_mpeg2_init, 697 FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), 698 .close = &vaapi_encode_mpeg2_close, 699 .p.priv_class = &vaapi_encode_mpeg2_class, 700 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | 701 AV_CODEC_CAP_DR1, 702 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, 703 .defaults = vaapi_encode_mpeg2_defaults, 704 .p.pix_fmts = (const enum AVPixelFormat[]) { 705 AV_PIX_FMT_VAAPI, 706 AV_PIX_FMT_NONE, 707 }, 708 .hw_configs = ff_vaapi_encode_hw_configs, 709 .p.wrapper_name = "vaapi", 710}; 711