mediacodecenc.c (52727B)
1 /* 2 * Android MediaCodec encoders 3 * 4 * Copyright (c) 2022 Zhao Zhili <zhilizhao@tencent.com> 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 #include "config_components.h" 24 25 #include "libavutil/avassert.h" 26 #include "libavutil/fifo.h" 27 #include "libavutil/avstring.h" 28 #include "libavutil/hwcontext_mediacodec.h" 29 #include "libavutil/imgutils.h" 30 #include "libavutil/mem.h" 31 #include "libavutil/opt.h" 32 #include "libavutil/thread.h" 33 34 #include "avcodec.h" 35 #include "bsf.h" 36 #include "codec_internal.h" 37 #include "encode.h" 38 #include "hwconfig.h" 39 #include "fffjni.h" 40 #include "mediacodec.h" 41 #include "mediacodec_wrapper.h" 42 #include "mediacodecdec_common.h" 43 #include "profiles.h" 44 45 #define INPUT_DEQUEUE_TIMEOUT_US 8000 46 #define OUTPUT_DEQUEUE_TIMEOUT_US 8000 47 48 enum BitrateMode { 49 /* Constant quality mode */ 50 BITRATE_MODE_CQ = 0, 51 /* Variable bitrate mode */ 52 BITRATE_MODE_VBR = 1, 53 /* Constant bitrate mode */ 54 BITRATE_MODE_CBR = 2, 55 /* Constant bitrate mode with frame drops */ 56 BITRATE_MODE_CBR_FD = 3, 57 }; 58 59 typedef struct MediaCodecAsyncOutput { 60 int32_t index; 61 FFAMediaCodecBufferInfo buf_info; 62 } MediaCodecAsyncOutput; 63 64 typedef struct MediaCodecEncContext { 65 AVClass *avclass; 66 FFAMediaCodec *codec; 67 int use_ndk_codec; 68 const char *name; 69 FFANativeWindow *window; 70 71 int fps; 72 int width; 73 int height; 74 75 uint8_t *extradata; 76 int extradata_size; 77 int eof_sent; 78 79 AVFrame *frame; 80 AVBSFContext *bsf; 81 82 int bitrate_mode; 83 int level; 84 int pts_as_dts; 85 int extract_extradata; 86 // Ref. MediaFormat KEY_OPERATING_RATE 87 int operating_rate; 88 int async_mode; 89 90 AVMutex input_mutex; 91 AVCond input_cond; 92 AVFifo *input_index; 93 94 AVMutex output_mutex; 95 AVCond output_cond; 96 int encode_status; 97 AVFifo *async_output; 98 } MediaCodecEncContext; 99 100 enum { 101 COLOR_FormatYUV420Planar = 0x13, 102 COLOR_FormatYUV420SemiPlanar = 0x15, 103 COLOR_FormatSurface = 0x7F000789, 104 }; 105 106 static const struct { 107 int color_format; 108 enum AVPixelFormat pix_fmt; 109 } color_formats[] = { 110 { COLOR_FormatYUV420Planar, AV_PIX_FMT_YUV420P }, 111 { COLOR_FormatYUV420SemiPlanar, AV_PIX_FMT_NV12 }, 112 { COLOR_FormatSurface, AV_PIX_FMT_MEDIACODEC }, 113 }; 114 115 static const enum AVPixelFormat avc_pix_fmts[] = { 116 AV_PIX_FMT_MEDIACODEC, 117 AV_PIX_FMT_YUV420P, 118 AV_PIX_FMT_NV12, 119 AV_PIX_FMT_NONE 120 }; 121 122 static void mediacodec_dump_format(AVCodecContext *avctx, 123 FFAMediaFormat *out_format) 124 { 125 MediaCodecEncContext *s = avctx->priv_data; 126 const char *name = s->name; 127 char *str = ff_AMediaFormat_toString(out_format); 128 129 av_log(avctx, AV_LOG_DEBUG, "MediaCodec encoder %s output format %s\n", 130 name ? name : "unknown", str); 131 av_free(str); 132 } 133 134 static void mediacodec_output_format(AVCodecContext *avctx) 135 { 136 MediaCodecEncContext *s = avctx->priv_data; 137 FFAMediaFormat *out_format = ff_AMediaCodec_getOutputFormat(s->codec); 138 139 if (!s->name) 140 s->name = ff_AMediaCodec_getName(s->codec); 141 mediacodec_dump_format(avctx, out_format); 142 ff_AMediaFormat_delete(out_format); 143 } 144 145 static int extract_extradata_support(AVCodecContext *avctx) 146 { 147 const AVBitStreamFilter *bsf = av_bsf_get_by_name("extract_extradata"); 148 149 if (!bsf) { 150 av_log(avctx, AV_LOG_WARNING, "extract_extradata bsf not found\n"); 151 return 0; 152 } 153 154 for (int i = 0; bsf->codec_ids[i] != AV_CODEC_ID_NONE; i++) { 155 if (bsf->codec_ids[i] == avctx->codec_id) 156 return 1; 157 } 158 159 return 0; 160 } 161 162 static int mediacodec_init_bsf(AVCodecContext *avctx) 163 { 164 MediaCodecEncContext *s = avctx->priv_data; 165 char str[128] = {0}; 166 int ret; 167 int crop_right = s->width - avctx->width; 168 int crop_bottom = s->height - avctx->height; 169 170 /* Nothing can be done for this format now */ 171 if (avctx->pix_fmt == AV_PIX_FMT_MEDIACODEC) 172 return 0; 173 174 s->extract_extradata = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) && 175 extract_extradata_support(avctx); 176 if (!crop_right && !crop_bottom && !s->extract_extradata) 177 return 0; 178 179 ret = 0; 180 if (crop_right || crop_bottom) { 181 if (avctx->codec_id == AV_CODEC_ID_H264) 182 ret = snprintf(str, sizeof(str), "h264_metadata=crop_right=%d:crop_bottom=%d", 183 crop_right, crop_bottom); 184 else if (avctx->codec_id == AV_CODEC_ID_HEVC) 185 /* Encoder can use CTU size larger than 16x16, so the real crop 186 * margin can be larger than crop_right/crop_bottom. Let bsf figure 187 * out the real crop margin. 188 */ 189 ret = snprintf(str, sizeof(str), "hevc_metadata=width=%d:height=%d", 190 avctx->width, avctx->height); 191 if (ret >= sizeof(str)) 192 return AVERROR_BUFFER_TOO_SMALL; 193 } 194 195 if (s->extract_extradata) { 196 ret = av_strlcatf(str, sizeof(str), "%sextract_extradata", ret ? "," : ""); 197 if (ret >= sizeof(str)) 198 return AVERROR_BUFFER_TOO_SMALL; 199 } 200 201 ret = av_bsf_list_parse_str(str, &s->bsf); 202 if (ret < 0) 203 return ret; 204 205 ret = avcodec_parameters_from_context(s->bsf->par_in, avctx); 206 if (ret < 0) 207 return ret; 208 s->bsf->time_base_in = avctx->time_base; 209 ret = av_bsf_init(s->bsf); 210 211 return ret; 212 } 213 214 static void copy_frame_to_buffer(AVCodecContext *avctx, const AVFrame *frame, 215 uint8_t *dst, size_t size) 216 { 217 MediaCodecEncContext *s = avctx->priv_data; 218 uint8_t *dst_data[4] = {}; 219 int dst_linesize[4] = {}; 220 221 if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { 222 dst_data[0] = dst; 223 dst_data[1] = dst + s->width * s->height; 224 dst_data[2] = dst_data[1] + s->width * s->height / 4; 225 226 dst_linesize[0] = s->width; 227 dst_linesize[1] = dst_linesize[2] = s->width / 2; 228 } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) { 229 dst_data[0] = dst; 230 dst_data[1] = dst + s->width * s->height; 231 232 dst_linesize[0] = s->width; 233 dst_linesize[1] = s->width; 234 } else { 235 av_assert0(0); 236 } 237 238 av_image_copy2(dst_data, dst_linesize, frame->data, frame->linesize, 239 avctx->pix_fmt, avctx->width, avctx->height); 240 } 241 242 243 static void on_error(FFAMediaCodec *codec, void *userdata, int error, 244 const char *detail) 245 { 246 AVCodecContext *avctx = userdata; 247 MediaCodecEncContext *s = avctx->priv_data; 248 249 if (error == AVERROR(EAGAIN)) 250 return; 251 252 av_log(avctx, AV_LOG_ERROR, "On error, %s, %s\n", av_err2str(error), detail); 253 254 ff_mutex_lock(&s->input_mutex); 255 ff_mutex_lock(&s->output_mutex); 256 s->encode_status = error; 257 ff_mutex_unlock(&s->output_mutex); 258 ff_mutex_unlock(&s->input_mutex); 259 260 ff_cond_signal(&s->output_cond); 261 ff_cond_signal(&s->input_cond); 262 } 263 264 static void on_input_available(FFAMediaCodec *codec, void *userdata, 265 int32_t index) 266 { 267 AVCodecContext *avctx = userdata; 268 MediaCodecEncContext *s = avctx->priv_data; 269 int ret; 270 271 ff_mutex_lock(&s->input_mutex); 272 ret = av_fifo_write(s->input_index, &index, 1); 273 if (ret >= 0) 274 ff_cond_signal(&s->input_cond); 275 ff_mutex_unlock(&s->input_mutex); 276 277 if (ret < 0) 278 on_error(codec, userdata, ret, "av_fifo_write failed"); 279 } 280 281 static void on_output_available(FFAMediaCodec *codec, void *userdata, 282 int32_t index, 283 FFAMediaCodecBufferInfo *out_info) 284 { 285 AVCodecContext *avctx = userdata; 286 MediaCodecEncContext *s = avctx->priv_data; 287 MediaCodecAsyncOutput output = { 288 .index = index, 289 .buf_info = *out_info, 290 }; 291 int ret; 292 293 ff_mutex_lock(&s->output_mutex); 294 ret = av_fifo_write(s->async_output, &output, 1); 295 if (ret >= 0) 296 ff_cond_signal(&s->output_cond); 297 ff_mutex_unlock(&s->output_mutex); 298 299 if (ret < 0) 300 on_error(codec, userdata, ret, "av_fifo_write failed"); 301 } 302 303 static void on_format_changed(FFAMediaCodec *codec, void *userdata, 304 FFAMediaFormat *format) 305 { 306 mediacodec_dump_format(userdata, format); 307 } 308 309 static int mediacodec_init_async_state(AVCodecContext *avctx) 310 { 311 MediaCodecEncContext *s = avctx->priv_data; 312 size_t fifo_size = 16; 313 314 if (!s->async_mode) 315 return 0; 316 317 ff_mutex_init(&s->input_mutex, NULL); 318 ff_cond_init(&s->input_cond, NULL); 319 320 ff_mutex_init(&s->output_mutex, NULL); 321 ff_cond_init(&s->output_cond, NULL); 322 323 s->input_index = av_fifo_alloc2(fifo_size, sizeof(int32_t), AV_FIFO_FLAG_AUTO_GROW); 324 s->async_output = av_fifo_alloc2(fifo_size, sizeof(MediaCodecAsyncOutput), 325 AV_FIFO_FLAG_AUTO_GROW); 326 327 if (!s->input_index || !s->async_output) 328 return AVERROR(ENOMEM); 329 330 return 0; 331 } 332 333 static void mediacodec_uninit_async_state(AVCodecContext *avctx) 334 { 335 MediaCodecEncContext *s = avctx->priv_data; 336 337 if (!s->async_mode) 338 return; 339 340 ff_mutex_destroy(&s->input_mutex); 341 ff_cond_destroy(&s->input_cond); 342 343 ff_mutex_destroy(&s->output_mutex); 344 ff_cond_destroy(&s->output_cond); 345 346 av_fifo_freep2(&s->input_index); 347 av_fifo_freep2(&s->async_output); 348 349 s->async_mode = 0; 350 } 351 352 static int mediacodec_generate_extradata(AVCodecContext *avctx); 353 354 static av_cold int mediacodec_init(AVCodecContext *avctx) 355 { 356 const char *codec_mime = NULL; 357 MediaCodecEncContext *s = avctx->priv_data; 358 FFAMediaFormat *format = NULL; 359 int ret; 360 int gop; 361 362 // Init async state first, so we can do cleanup safely on error path. 363 ret = mediacodec_init_async_state(avctx); 364 if (ret < 0) 365 return ret; 366 367 if (s->use_ndk_codec < 0) 368 s->use_ndk_codec = !av_jni_get_java_vm(avctx); 369 370 switch (avctx->codec_id) { 371 case AV_CODEC_ID_H264: 372 codec_mime = "video/avc"; 373 break; 374 case AV_CODEC_ID_HEVC: 375 codec_mime = "video/hevc"; 376 break; 377 case AV_CODEC_ID_VP8: 378 codec_mime = "video/x-vnd.on2.vp8"; 379 break; 380 case AV_CODEC_ID_VP9: 381 codec_mime = "video/x-vnd.on2.vp9"; 382 break; 383 case AV_CODEC_ID_MPEG4: 384 codec_mime = "video/mp4v-es"; 385 break; 386 case AV_CODEC_ID_AV1: 387 codec_mime = "video/av01"; 388 break; 389 default: 390 av_assert0(0); 391 } 392 393 if (s->name) 394 s->codec = ff_AMediaCodec_createCodecByName(s->name, s->use_ndk_codec); 395 else 396 s->codec = ff_AMediaCodec_createEncoderByType(codec_mime, s->use_ndk_codec); 397 if (!s->codec) { 398 av_log(avctx, AV_LOG_ERROR, "Failed to create encoder for type %s\n", 399 codec_mime); 400 return AVERROR_EXTERNAL; 401 } 402 403 format = ff_AMediaFormat_new(s->use_ndk_codec); 404 if (!format) { 405 av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n"); 406 return AVERROR_EXTERNAL; 407 } 408 409 ff_AMediaFormat_setString(format, "mime", codec_mime); 410 // Workaround the alignment requirement of mediacodec. We can't do it 411 // silently for AV_PIX_FMT_MEDIACODEC. 412 if (avctx->pix_fmt != AV_PIX_FMT_MEDIACODEC && 413 (avctx->codec_id == AV_CODEC_ID_H264 || 414 avctx->codec_id == AV_CODEC_ID_HEVC)) { 415 s->width = FFALIGN(avctx->width, 16); 416 s->height = FFALIGN(avctx->height, 16); 417 } else { 418 s->width = avctx->width; 419 s->height = avctx->height; 420 if (s->width % 16 || s->height % 16) 421 av_log(avctx, AV_LOG_WARNING, 422 "Video size %dx%d isn't align to 16, it may have device compatibility issue\n", 423 s->width, s->height); 424 } 425 ff_AMediaFormat_setInt32(format, "width", s->width); 426 ff_AMediaFormat_setInt32(format, "height", s->height); 427 428 if (avctx->pix_fmt == AV_PIX_FMT_MEDIACODEC) { 429 AVMediaCodecContext *user_ctx = avctx->hwaccel_context; 430 if (avctx->hw_device_ctx) { 431 AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); 432 AVMediaCodecDeviceContext *dev_ctx; 433 434 if (device_ctx->type != AV_HWDEVICE_TYPE_MEDIACODEC || !device_ctx->hwctx) { 435 ret = AVERROR(EINVAL); 436 goto bailout; 437 } 438 dev_ctx = device_ctx->hwctx; 439 s->window = ff_mediacodec_surface_ref(dev_ctx->surface, dev_ctx->native_window, avctx); 440 } 441 442 if (!s->window && user_ctx && user_ctx->surface) 443 s->window = ff_mediacodec_surface_ref(user_ctx->surface, NULL, avctx); 444 445 if (!s->window) { 446 ret = AVERROR(EINVAL); 447 av_log(avctx, AV_LOG_ERROR, "Missing hw_device_ctx or hwaccel_context for AV_PIX_FMT_MEDIACODEC\n"); 448 goto bailout; 449 } 450 /* Although there is a method ANativeWindow_toSurface() introduced in 451 * API level 26, it's easier and safe to always require a Surface for 452 * Java MediaCodec. 453 */ 454 if (!s->use_ndk_codec && !s->window->surface) { 455 ret = AVERROR(EINVAL); 456 av_log(avctx, AV_LOG_ERROR, "Missing jobject Surface for AV_PIX_FMT_MEDIACODEC. " 457 "Please note that Java MediaCodec doesn't work with ANativeWindow.\n"); 458 goto bailout; 459 } 460 } 461 462 for (int i = 0; i < FF_ARRAY_ELEMS(color_formats); i++) { 463 if (avctx->pix_fmt == color_formats[i].pix_fmt) { 464 ff_AMediaFormat_setInt32(format, "color-format", 465 color_formats[i].color_format); 466 break; 467 } 468 } 469 470 ret = ff_AMediaFormatColorRange_from_AVColorRange(avctx->color_range); 471 if (ret != COLOR_RANGE_UNSPECIFIED) 472 ff_AMediaFormat_setInt32(format, "color-range", ret); 473 ret = ff_AMediaFormatColorStandard_from_AVColorSpace(avctx->colorspace); 474 if (ret != COLOR_STANDARD_UNSPECIFIED) 475 ff_AMediaFormat_setInt32(format, "color-standard", ret); 476 ret = ff_AMediaFormatColorTransfer_from_AVColorTransfer(avctx->color_trc); 477 if (ret != COLOR_TRANSFER_UNSPECIFIED) 478 ff_AMediaFormat_setInt32(format, "color-transfer", ret); 479 480 if (avctx->bit_rate) 481 ff_AMediaFormat_setInt32(format, "bitrate", avctx->bit_rate); 482 if (s->bitrate_mode >= 0) { 483 ff_AMediaFormat_setInt32(format, "bitrate-mode", s->bitrate_mode); 484 if (s->bitrate_mode == BITRATE_MODE_CQ && avctx->global_quality > 0) 485 ff_AMediaFormat_setInt32(format, "quality", avctx->global_quality); 486 } 487 // frame-rate and i-frame-interval are required to configure codec 488 if (avctx->framerate.num >= avctx->framerate.den && avctx->framerate.den > 0) { 489 s->fps = avctx->framerate.num / avctx->framerate.den; 490 } else { 491 s->fps = 30; 492 av_log(avctx, AV_LOG_INFO, "Use %d as the default MediaFormat frame-rate\n", s->fps); 493 } 494 gop = round(avctx->gop_size / s->fps); 495 if (gop == 0) { 496 gop = 1; 497 av_log(avctx, AV_LOG_INFO, 498 "Use %d as the default MediaFormat i-frame-interval, " 499 "please set gop_size properly (>= fps)\n", gop); 500 } else { 501 av_log(avctx, AV_LOG_DEBUG, "Set i-frame-interval to %d\n", gop); 502 } 503 504 ff_AMediaFormat_setInt32(format, "frame-rate", s->fps); 505 ff_AMediaFormat_setInt32(format, "i-frame-interval", gop); 506 507 ret = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx); 508 if (ret > 0) { 509 av_log(avctx, AV_LOG_DEBUG, "set profile to 0x%x\n", ret); 510 ff_AMediaFormat_setInt32(format, "profile", ret); 511 } 512 if (s->level > 0) { 513 av_log(avctx, AV_LOG_DEBUG, "set level to 0x%x\n", s->level); 514 ff_AMediaFormat_setInt32(format, "level", s->level); 515 } 516 if (avctx->max_b_frames > 0) { 517 if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { 518 av_log(avctx, AV_LOG_ERROR, 519 "Enabling B frames will produce packets with no DTS. " 520 "Use -strict experimental to use it anyway.\n"); 521 ret = AVERROR(EINVAL); 522 goto bailout; 523 } 524 ff_AMediaFormat_setInt32(format, "max-bframes", avctx->max_b_frames); 525 } 526 if (s->pts_as_dts == -1) 527 s->pts_as_dts = avctx->max_b_frames <= 0; 528 if (s->operating_rate > 0) 529 ff_AMediaFormat_setInt32(format, "operating-rate", s->operating_rate); 530 531 ret = ff_AMediaCodec_getConfigureFlagEncode(s->codec); 532 ret = ff_AMediaCodec_configure(s->codec, format, s->window, NULL, ret); 533 if (ret) { 534 av_log(avctx, AV_LOG_ERROR, "MediaCodec configure failed, %s\n", av_err2str(ret)); 535 if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) 536 av_log(avctx, AV_LOG_ERROR, "Please try -pix_fmt nv12, some devices don't " 537 "support yuv420p as encoder input format.\n"); 538 goto bailout; 539 } 540 541 if (s->async_mode) { 542 FFAMediaCodecOnAsyncNotifyCallback cb = { 543 .onAsyncInputAvailable = on_input_available, 544 .onAsyncOutputAvailable = on_output_available, 545 .onAsyncFormatChanged = on_format_changed, 546 .onAsyncError = on_error, 547 }; 548 549 ret = ff_AMediaCodec_setAsyncNotifyCallback(s->codec, &cb, avctx); 550 if (ret < 0) { 551 av_log(avctx, AV_LOG_WARNING, 552 "Try MediaCodec async mode failed, %s, switch to sync mode\n", 553 av_err2str(ret)); 554 mediacodec_uninit_async_state(avctx); 555 } 556 } 557 558 ret = mediacodec_init_bsf(avctx); 559 if (ret) 560 goto bailout; 561 562 mediacodec_output_format(avctx); 563 564 s->frame = av_frame_alloc(); 565 if (!s->frame) { 566 ret = AVERROR(ENOMEM); 567 goto bailout; 568 } 569 570 ret = ff_AMediaCodec_start(s->codec); 571 if (ret) { 572 av_log(avctx, AV_LOG_ERROR, "MediaCodec failed to start, %s\n", 573 av_err2str(ret)); 574 goto bailout; 575 } 576 577 ret = mediacodec_generate_extradata(avctx); 578 579 bailout: 580 if (format) 581 ff_AMediaFormat_delete(format); 582 return ret; 583 } 584 585 static int mediacodec_get_output_index(AVCodecContext *avctx, ssize_t *index, 586 FFAMediaCodecBufferInfo *out_info) 587 { 588 MediaCodecEncContext *s = avctx->priv_data; 589 FFAMediaCodec *codec = s->codec; 590 int64_t timeout_us = s->eof_sent ? OUTPUT_DEQUEUE_TIMEOUT_US : 0; 591 MediaCodecAsyncOutput output = { .index = -1 }; 592 int ret; 593 594 if (!s->async_mode) { 595 *index = ff_AMediaCodec_dequeueOutputBuffer(codec, out_info, timeout_us); 596 return 0; 597 } 598 599 ff_mutex_lock(&s->output_mutex); 600 601 while (!s->encode_status) { 602 if (av_fifo_read(s->async_output, &output, 1) >= 0) 603 break; 604 605 // Only wait after signalEndOfInputStream 606 if (s->eof_sent && !s->encode_status) 607 ff_cond_wait(&s->output_cond, &s->output_mutex); 608 else 609 break; 610 } 611 612 ret = s->encode_status; 613 ff_mutex_unlock(&s->output_mutex); 614 615 // Get output index success 616 if (output.index >= 0) { 617 *index = output.index; 618 *out_info = output.buf_info; 619 return 0; 620 } 621 622 return ret ? ret : AVERROR(EAGAIN); 623 } 624 625 static int mediacodec_receive(AVCodecContext *avctx, AVPacket *pkt) 626 { 627 MediaCodecEncContext *s = avctx->priv_data; 628 FFAMediaCodec *codec = s->codec; 629 ssize_t index; 630 FFAMediaCodecBufferInfo out_info = {0}; 631 uint8_t *out_buf; 632 size_t out_size = 0; 633 int ret; 634 int extradata_size = 0; 635 636 ret = mediacodec_get_output_index(avctx, &index, &out_info); 637 if (ret < 0) 638 return ret; 639 640 if (ff_AMediaCodec_infoTryAgainLater(codec, index)) 641 return AVERROR(EAGAIN); 642 643 if (ff_AMediaCodec_infoOutputFormatChanged(codec, index)) { 644 mediacodec_output_format(avctx); 645 return AVERROR(EAGAIN); 646 } 647 648 if (ff_AMediaCodec_infoOutputBuffersChanged(codec, index)) { 649 ff_AMediaCodec_cleanOutputBuffers(codec); 650 return AVERROR(EAGAIN); 651 } 652 653 if (index < 0) 654 return AVERROR_EXTERNAL; 655 656 if (out_info.flags & ff_AMediaCodec_getBufferFlagEndOfStream(codec)) 657 return AVERROR_EOF; 658 659 out_buf = ff_AMediaCodec_getOutputBuffer(codec, index, &out_size); 660 if (!out_buf) { 661 ret = AVERROR_EXTERNAL; 662 goto bailout; 663 } 664 665 if (out_info.flags & ff_AMediaCodec_getBufferFlagCodecConfig(codec)) { 666 if (avctx->codec_id == AV_CODEC_ID_AV1) { 667 // Skip AV1CodecConfigurationRecord without configOBUs 668 if (out_info.size <= 4) { 669 ff_AMediaCodec_releaseOutputBuffer(codec, index, false); 670 return mediacodec_receive(avctx, pkt); 671 } 672 out_info.size -= 4; 673 out_info.offset += 4; 674 } 675 676 ret = av_reallocp(&s->extradata, out_info.size); 677 if (ret) 678 goto bailout; 679 680 s->extradata_size = out_info.size; 681 memcpy(s->extradata, out_buf + out_info.offset, out_info.size); 682 ff_AMediaCodec_releaseOutputBuffer(codec, index, false); 683 // try immediately 684 return mediacodec_receive(avctx, pkt); 685 } 686 687 ret = ff_get_encode_buffer(avctx, pkt, out_info.size + s->extradata_size, 0); 688 if (ret < 0) 689 goto bailout; 690 691 if (s->extradata_size) { 692 extradata_size = s->extradata_size; 693 s->extradata_size = 0; 694 memcpy(pkt->data, s->extradata, extradata_size); 695 } 696 memcpy(pkt->data + extradata_size, out_buf + out_info.offset, out_info.size); 697 pkt->pts = av_rescale_q(out_info.presentationTimeUs, AV_TIME_BASE_Q, avctx->time_base); 698 if (s->pts_as_dts) 699 pkt->dts = pkt->pts; 700 if (out_info.flags & ff_AMediaCodec_getBufferFlagKeyFrame(codec)) 701 pkt->flags |= AV_PKT_FLAG_KEY; 702 ret = 0; 703 704 av_log(avctx, AV_LOG_TRACE, "receive packet pts %" PRId64 " dts %" PRId64 705 " flags %d extradata %d\n", 706 pkt->pts, pkt->dts, pkt->flags, extradata_size); 707 708 bailout: 709 ff_AMediaCodec_releaseOutputBuffer(codec, index, false); 710 return ret; 711 } 712 713 static int mediacodec_get_input_index(AVCodecContext *avctx, ssize_t *index) 714 { 715 MediaCodecEncContext *s = avctx->priv_data; 716 FFAMediaCodec *codec = s->codec; 717 int ret = 0; 718 int32_t n; 719 720 if (!s->async_mode) { 721 *index = ff_AMediaCodec_dequeueInputBuffer(codec, INPUT_DEQUEUE_TIMEOUT_US); 722 return 0; 723 } 724 725 ff_mutex_lock(&s->input_mutex); 726 727 n = -1; 728 while (n < 0 && !s->encode_status) { 729 if (av_fifo_can_read(s->input_index) > 0) { 730 av_fifo_read(s->input_index, &n, 1); 731 break; 732 } 733 734 if (n < 0 && !s->encode_status) 735 ff_cond_wait(&s->input_cond, &s->input_mutex); 736 } 737 738 ret = s->encode_status; 739 *index = n; 740 ff_mutex_unlock(&s->input_mutex); 741 742 return ret; 743 } 744 745 746 static int mediacodec_send(AVCodecContext *avctx, 747 const AVFrame *frame) { 748 MediaCodecEncContext *s = avctx->priv_data; 749 FFAMediaCodec *codec = s->codec; 750 ssize_t index; 751 uint8_t *input_buf = NULL; 752 size_t input_size = 0; 753 int64_t pts = 0; 754 uint32_t flags = 0; 755 int ret; 756 757 if (s->eof_sent) 758 return 0; 759 760 if (s->window) { 761 if (!frame) { 762 s->eof_sent = 1; 763 return ff_AMediaCodec_signalEndOfInputStream(codec); 764 } 765 766 if (frame->data[3]) 767 av_mediacodec_release_buffer((AVMediaCodecBuffer *)frame->data[3], 1); 768 return 0; 769 } 770 771 ret = mediacodec_get_input_index(avctx, &index); 772 if (ret < 0) 773 return ret; 774 775 if (ff_AMediaCodec_infoTryAgainLater(codec, index)) 776 return AVERROR(EAGAIN); 777 778 if (index < 0) { 779 av_log(avctx, AV_LOG_ERROR, "dequeue input buffer failed, %zd", index); 780 return AVERROR_EXTERNAL; 781 } 782 783 if (frame) { 784 input_buf = ff_AMediaCodec_getInputBuffer(codec, index, &input_size); 785 copy_frame_to_buffer(avctx, frame, input_buf, input_size); 786 787 pts = av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q); 788 789 if (frame->pict_type == AV_PICTURE_TYPE_I) { 790 FFAMediaFormat *format = ff_AMediaFormat_new(s->use_ndk_codec); 791 ff_AMediaFormat_setInt32(format, "request-sync", 0); 792 ff_AMediaCodec_setParameters(codec, format); 793 ff_AMediaFormat_delete(format); 794 } 795 } else { 796 flags |= ff_AMediaCodec_getBufferFlagEndOfStream(codec); 797 s->eof_sent = 1; 798 } 799 800 ff_AMediaCodec_queueInputBuffer(codec, index, 0, input_size, pts, flags); 801 return 0; 802 } 803 804 static int mediacodec_encode(AVCodecContext *avctx, AVPacket *pkt) 805 { 806 MediaCodecEncContext *s = avctx->priv_data; 807 int ret; 808 809 // Return on three case: 810 // 1. Serious error 811 // 2. Got a packet success 812 // 3. No AVFrame is available yet (don't return if get_frame return EOF) 813 while (1) { 814 if (s->bsf) { 815 ret = av_bsf_receive_packet(s->bsf, pkt); 816 if (!ret) 817 return 0; 818 if (ret != AVERROR(EAGAIN)) 819 return ret; 820 } 821 822 ret = mediacodec_receive(avctx, pkt); 823 if (s->bsf) { 824 if (!ret || ret == AVERROR_EOF) 825 ret = av_bsf_send_packet(s->bsf, pkt); 826 } else { 827 if (!ret) 828 return 0; 829 } 830 831 if (ret < 0 && ret != AVERROR(EAGAIN)) 832 return ret; 833 834 if (!s->frame->buf[0]) { 835 ret = ff_encode_get_frame(avctx, s->frame); 836 if (ret && ret != AVERROR_EOF) 837 return ret; 838 } 839 840 ret = mediacodec_send(avctx, s->frame->buf[0] ? s->frame : NULL); 841 if (!ret) 842 av_frame_unref(s->frame); 843 else if (ret != AVERROR(EAGAIN)) 844 return ret; 845 } 846 847 return 0; 848 } 849 850 static int mediacodec_send_dummy_frame(AVCodecContext *avctx) 851 { 852 MediaCodecEncContext *s = avctx->priv_data; 853 int ret; 854 855 s->frame->width = avctx->width; 856 s->frame->height = avctx->height; 857 s->frame->format = avctx->pix_fmt; 858 s->frame->pts = 0; 859 860 ret = av_frame_get_buffer(s->frame, 0); 861 if (ret < 0) 862 return ret; 863 864 do { 865 ret = mediacodec_send(avctx, s->frame); 866 } while (ret == AVERROR(EAGAIN)); 867 av_frame_unref(s->frame); 868 869 if (ret < 0) 870 return ret; 871 872 ret = mediacodec_send(avctx, NULL); 873 if (ret < 0) { 874 av_log(avctx, AV_LOG_ERROR, "Flush failed: %s\n", av_err2str(ret)); 875 return ret; 876 } 877 878 return 0; 879 } 880 881 static int mediacodec_receive_dummy_pkt(AVCodecContext *avctx, AVPacket *pkt) 882 { 883 MediaCodecEncContext *s = avctx->priv_data; 884 int ret; 885 886 do { 887 ret = mediacodec_receive(avctx, pkt); 888 } while (ret == AVERROR(EAGAIN)); 889 890 if (ret < 0) 891 return ret; 892 893 do { 894 ret = av_bsf_send_packet(s->bsf, pkt); 895 if (ret < 0) 896 return ret; 897 ret = av_bsf_receive_packet(s->bsf, pkt); 898 } while (ret == AVERROR(EAGAIN)); 899 900 return ret; 901 } 902 903 static int mediacodec_generate_extradata(AVCodecContext *avctx) 904 { 905 MediaCodecEncContext *s = avctx->priv_data; 906 AVPacket *pkt = NULL; 907 int ret; 908 size_t side_size; 909 uint8_t *side; 910 911 if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) 912 return 0; 913 914 // Send dummy frame and receive a packet doesn't work in async mode 915 if (s->async_mode || !s->extract_extradata) { 916 av_log(avctx, AV_LOG_WARNING, 917 "Mediacodec encoder doesn't support AV_CODEC_FLAG_GLOBAL_HEADER. " 918 "Use extract_extradata bsf when necessary.\n"); 919 return 0; 920 } 921 922 pkt = av_packet_alloc(); 923 if (!pkt) 924 return AVERROR(ENOMEM); 925 926 ret = mediacodec_send_dummy_frame(avctx); 927 if (ret < 0) 928 goto bailout; 929 ret = mediacodec_receive_dummy_pkt(avctx, pkt); 930 if (ret < 0) 931 goto bailout; 932 933 side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); 934 if (side && side_size > 0) { 935 avctx->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); 936 if (!avctx->extradata) { 937 ret = AVERROR(ENOMEM); 938 goto bailout; 939 } 940 941 memcpy(avctx->extradata, side, side_size); 942 avctx->extradata_size = side_size; 943 } 944 945 bailout: 946 if (s->eof_sent) { 947 s->eof_sent = 0; 948 ff_AMediaCodec_flush(s->codec); 949 } 950 av_bsf_flush(s->bsf); 951 av_packet_free(&pkt); 952 return ret; 953 } 954 955 static av_cold int mediacodec_close(AVCodecContext *avctx) 956 { 957 MediaCodecEncContext *s = avctx->priv_data; 958 if (s->codec) { 959 ff_AMediaCodec_stop(s->codec); 960 ff_AMediaCodec_delete(s->codec); 961 s->codec = NULL; 962 } 963 964 if (s->window) { 965 ff_mediacodec_surface_unref(s->window, avctx); 966 s->window = NULL; 967 } 968 969 av_bsf_free(&s->bsf); 970 av_frame_free(&s->frame); 971 972 mediacodec_uninit_async_state(avctx); 973 974 return 0; 975 } 976 977 static av_cold void mediacodec_flush(AVCodecContext *avctx) 978 { 979 MediaCodecEncContext *s = avctx->priv_data; 980 if (s->bsf) 981 av_bsf_flush(s->bsf); 982 av_frame_unref(s->frame); 983 ff_AMediaCodec_flush(s->codec); 984 } 985 986 static const AVCodecHWConfigInternal *const mediacodec_hw_configs[] = { 987 &(const AVCodecHWConfigInternal) { 988 .public = { 989 .pix_fmt = AV_PIX_FMT_MEDIACODEC, 990 .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC | 991 AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, 992 .device_type = AV_HWDEVICE_TYPE_MEDIACODEC, 993 }, 994 .hwaccel = NULL, 995 }, 996 NULL 997 }; 998 999 #define OFFSET(x) offsetof(MediaCodecEncContext, x) 1000 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 1001 #define COMMON_OPTION \ 1002 { "ndk_codec", "Use MediaCodec from NDK", \ 1003 OFFSET(use_ndk_codec), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE }, \ 1004 { "ndk_async", "Try NDK MediaCodec in async mode", \ 1005 OFFSET(async_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE }, \ 1006 { "codec_name", "Select codec by name", \ 1007 OFFSET(name), AV_OPT_TYPE_STRING, {0}, 0, 0, VE }, \ 1008 { "bitrate_mode", "Bitrate control method", \ 1009 OFFSET(bitrate_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, .unit = "bitrate_mode" }, \ 1010 { "cq", "Constant quality mode", \ 1011 0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CQ}, 0, 0, VE, .unit = "bitrate_mode" }, \ 1012 { "vbr", "Variable bitrate mode", \ 1013 0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_VBR}, 0, 0, VE, .unit = "bitrate_mode" }, \ 1014 { "cbr", "Constant bitrate mode", \ 1015 0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CBR}, 0, 0, VE, .unit = "bitrate_mode" }, \ 1016 { "cbr_fd", "Constant bitrate mode with frame drops", \ 1017 0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CBR_FD}, 0, 0, VE, .unit = "bitrate_mode" }, \ 1018 { "pts_as_dts", "Use PTS as DTS. It is enabled automatically if avctx max_b_frames <= 0, " \ 1019 "since most of Android devices don't output B frames by default.", \ 1020 OFFSET(pts_as_dts), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE }, \ 1021 { "operating_rate", "The desired operating rate that the codec will need to operate at, zero for unspecified", \ 1022 OFFSET(operating_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE }, \ 1023 1024 #define MEDIACODEC_ENCODER_CLASS(name) \ 1025 static const AVClass name ## _mediacodec_class = { \ 1026 .class_name = #name "_mediacodec", \ 1027 .item_name = av_default_item_name, \ 1028 .option = name ## _options, \ 1029 .version = LIBAVUTIL_VERSION_INT, \ 1030 }; \ 1031 1032 #define DECLARE_MEDIACODEC_ENCODER(short_name, long_name, codec_id) \ 1033 MEDIACODEC_ENCODER_CLASS(short_name) \ 1034 const FFCodec ff_ ## short_name ## _mediacodec_encoder = { \ 1035 .p.name = #short_name "_mediacodec", \ 1036 CODEC_LONG_NAME(long_name " Android MediaCodec encoder"), \ 1037 .p.type = AVMEDIA_TYPE_VIDEO, \ 1038 .p.id = codec_id, \ 1039 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | \ 1040 AV_CODEC_CAP_HARDWARE | \ 1041 AV_CODEC_CAP_ENCODER_FLUSH, \ 1042 .priv_data_size = sizeof(MediaCodecEncContext), \ 1043 .p.pix_fmts = avc_pix_fmts, \ 1044 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, \ 1045 .init = mediacodec_init, \ 1046 FF_CODEC_RECEIVE_PACKET_CB(mediacodec_encode), \ 1047 .close = mediacodec_close, \ 1048 .flush = mediacodec_flush, \ 1049 .p.priv_class = &short_name ## _mediacodec_class, \ 1050 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ 1051 .p.wrapper_name = "mediacodec", \ 1052 .hw_configs = mediacodec_hw_configs, \ 1053 }; \ 1054 1055 #if CONFIG_H264_MEDIACODEC_ENCODER 1056 1057 enum MediaCodecAvcLevel { 1058 AVCLevel1 = 0x01, 1059 AVCLevel1b = 0x02, 1060 AVCLevel11 = 0x04, 1061 AVCLevel12 = 0x08, 1062 AVCLevel13 = 0x10, 1063 AVCLevel2 = 0x20, 1064 AVCLevel21 = 0x40, 1065 AVCLevel22 = 0x80, 1066 AVCLevel3 = 0x100, 1067 AVCLevel31 = 0x200, 1068 AVCLevel32 = 0x400, 1069 AVCLevel4 = 0x800, 1070 AVCLevel41 = 0x1000, 1071 AVCLevel42 = 0x2000, 1072 AVCLevel5 = 0x4000, 1073 AVCLevel51 = 0x8000, 1074 AVCLevel52 = 0x10000, 1075 AVCLevel6 = 0x20000, 1076 AVCLevel61 = 0x40000, 1077 AVCLevel62 = 0x80000, 1078 }; 1079 1080 static const AVOption h264_options[] = { 1081 COMMON_OPTION 1082 1083 FF_AVCTX_PROFILE_OPTION("baseline", NULL, VIDEO, AV_PROFILE_H264_BASELINE) 1084 FF_AVCTX_PROFILE_OPTION("constrained_baseline", NULL, VIDEO, AV_PROFILE_H264_CONSTRAINED_BASELINE) 1085 FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, AV_PROFILE_H264_MAIN) 1086 FF_AVCTX_PROFILE_OPTION("extended", NULL, VIDEO, AV_PROFILE_H264_EXTENDED) 1087 FF_AVCTX_PROFILE_OPTION("high", NULL, VIDEO, AV_PROFILE_H264_HIGH) 1088 FF_AVCTX_PROFILE_OPTION("high10", NULL, VIDEO, AV_PROFILE_H264_HIGH_10) 1089 FF_AVCTX_PROFILE_OPTION("high422", NULL, VIDEO, AV_PROFILE_H264_HIGH_422) 1090 FF_AVCTX_PROFILE_OPTION("high444", NULL, VIDEO, AV_PROFILE_H264_HIGH_444) 1091 1092 { "level", "Specify level", 1093 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1094 { "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel1 }, 0, 0, VE, .unit = "level" }, 1095 { "1b", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel1b }, 0, 0, VE, .unit = "level" }, 1096 { "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel11 }, 0, 0, VE, .unit = "level" }, 1097 { "1.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel12 }, 0, 0, VE, .unit = "level" }, 1098 { "1.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel13 }, 0, 0, VE, .unit = "level" }, 1099 { "2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel2 }, 0, 0, VE, .unit = "level" }, 1100 { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel21 }, 0, 0, VE, .unit = "level" }, 1101 { "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel22 }, 0, 0, VE, .unit = "level" }, 1102 { "3", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel3 }, 0, 0, VE, .unit = "level" }, 1103 { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel31 }, 0, 0, VE, .unit = "level" }, 1104 { "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel32 }, 0, 0, VE, .unit = "level" }, 1105 { "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel4 }, 0, 0, VE, .unit = "level" }, 1106 { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel41 }, 0, 0, VE, .unit = "level" }, 1107 { "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel42 }, 0, 0, VE, .unit = "level" }, 1108 { "5", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel5 }, 0, 0, VE, .unit = "level" }, 1109 { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel51 }, 0, 0, VE, .unit = "level" }, 1110 { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel52 }, 0, 0, VE, .unit = "level" }, 1111 { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel6 }, 0, 0, VE, .unit = "level" }, 1112 { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel61 }, 0, 0, VE, .unit = "level" }, 1113 { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel62 }, 0, 0, VE, .unit = "level" }, 1114 { NULL, } 1115 }; 1116 1117 DECLARE_MEDIACODEC_ENCODER(h264, "H.264", AV_CODEC_ID_H264) 1118 1119 #endif // CONFIG_H264_MEDIACODEC_ENCODER 1120 1121 #if CONFIG_HEVC_MEDIACODEC_ENCODER 1122 1123 enum MediaCodecHevcLevel { 1124 HEVCMainTierLevel1 = 0x1, 1125 HEVCHighTierLevel1 = 0x2, 1126 HEVCMainTierLevel2 = 0x4, 1127 HEVCHighTierLevel2 = 0x8, 1128 HEVCMainTierLevel21 = 0x10, 1129 HEVCHighTierLevel21 = 0x20, 1130 HEVCMainTierLevel3 = 0x40, 1131 HEVCHighTierLevel3 = 0x80, 1132 HEVCMainTierLevel31 = 0x100, 1133 HEVCHighTierLevel31 = 0x200, 1134 HEVCMainTierLevel4 = 0x400, 1135 HEVCHighTierLevel4 = 0x800, 1136 HEVCMainTierLevel41 = 0x1000, 1137 HEVCHighTierLevel41 = 0x2000, 1138 HEVCMainTierLevel5 = 0x4000, 1139 HEVCHighTierLevel5 = 0x8000, 1140 HEVCMainTierLevel51 = 0x10000, 1141 HEVCHighTierLevel51 = 0x20000, 1142 HEVCMainTierLevel52 = 0x40000, 1143 HEVCHighTierLevel52 = 0x80000, 1144 HEVCMainTierLevel6 = 0x100000, 1145 HEVCHighTierLevel6 = 0x200000, 1146 HEVCMainTierLevel61 = 0x400000, 1147 HEVCHighTierLevel61 = 0x800000, 1148 HEVCMainTierLevel62 = 0x1000000, 1149 HEVCHighTierLevel62 = 0x2000000, 1150 }; 1151 1152 static const AVOption hevc_options[] = { 1153 COMMON_OPTION 1154 1155 FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, AV_PROFILE_HEVC_MAIN) 1156 FF_AVCTX_PROFILE_OPTION("main10", NULL, VIDEO, AV_PROFILE_HEVC_MAIN_10) 1157 1158 { "level", "Specify tier and level", 1159 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1160 { "m1", "Main tier level 1", 1161 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel1 }, 0, 0, VE, .unit = "level" }, 1162 { "h1", "High tier level 1", 1163 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel1 }, 0, 0, VE, .unit = "level" }, 1164 { "m2", "Main tier level 2", 1165 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel2 }, 0, 0, VE, .unit = "level" }, 1166 { "h2", "High tier level 2", 1167 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel2 }, 0, 0, VE, .unit = "level" }, 1168 { "m2.1", "Main tier level 2.1", 1169 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel21 }, 0, 0, VE, .unit = "level" }, 1170 { "h2.1", "High tier level 2.1", 1171 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel21 }, 0, 0, VE, .unit = "level" }, 1172 { "m3", "Main tier level 3", 1173 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel3 }, 0, 0, VE, .unit = "level" }, 1174 { "h3", "High tier level 3", 1175 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel3 }, 0, 0, VE, .unit = "level" }, 1176 { "m3.1", "Main tier level 3.1", 1177 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel31 }, 0, 0, VE, .unit = "level" }, 1178 { "h3.1", "High tier level 3.1", 1179 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel31 }, 0, 0, VE, .unit = "level" }, 1180 { "m4", "Main tier level 4", 1181 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel4 }, 0, 0, VE, .unit = "level" }, 1182 { "h4", "High tier level 4", 1183 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel4 }, 0, 0, VE, .unit = "level" }, 1184 { "m4.1", "Main tier level 4.1", 1185 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel41 }, 0, 0, VE, .unit = "level" }, 1186 { "h4.1", "High tier level 4.1", 1187 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel41 }, 0, 0, VE, .unit = "level" }, 1188 { "m5", "Main tier level 5", 1189 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel5 }, 0, 0, VE, .unit = "level" }, 1190 { "h5", "High tier level 5", 1191 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel5 }, 0, 0, VE, .unit = "level" }, 1192 { "m5.1", "Main tier level 5.1", 1193 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel51 }, 0, 0, VE, .unit = "level" }, 1194 { "h5.1", "High tier level 5.1", 1195 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel51 }, 0, 0, VE, .unit = "level" }, 1196 { "m5.2", "Main tier level 5.2", 1197 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel52 }, 0, 0, VE, .unit = "level" }, 1198 { "h5.2", "High tier level 5.2", 1199 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel52 }, 0, 0, VE, .unit = "level" }, 1200 { "m6", "Main tier level 6", 1201 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel6 }, 0, 0, VE, .unit = "level" }, 1202 { "h6", "High tier level 6", 1203 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel6 }, 0, 0, VE, .unit = "level" }, 1204 { "m6.1", "Main tier level 6.1", 1205 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel61 }, 0, 0, VE, .unit = "level" }, 1206 { "h6.1", "High tier level 6.1", 1207 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel61 }, 0, 0, VE, .unit = "level" }, 1208 { "m6.2", "Main tier level 6.2", 1209 0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel62 }, 0, 0, VE, .unit = "level" }, 1210 { "h6.2", "High tier level 6.2", 1211 0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel62 }, 0, 0, VE, .unit = "level" }, 1212 { NULL, } 1213 }; 1214 1215 DECLARE_MEDIACODEC_ENCODER(hevc, "H.265", AV_CODEC_ID_HEVC) 1216 1217 #endif // CONFIG_HEVC_MEDIACODEC_ENCODER 1218 1219 #if CONFIG_VP8_MEDIACODEC_ENCODER 1220 1221 enum MediaCodecVP8Level { 1222 VP8Level_Version0 = 0x01, 1223 VP8Level_Version1 = 0x02, 1224 VP8Level_Version2 = 0x04, 1225 VP8Level_Version3 = 0x08, 1226 }; 1227 1228 static const AVOption vp8_options[] = { 1229 COMMON_OPTION 1230 { "level", "Specify tier and level", 1231 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1232 { "V0", "Level Version 0", 1233 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version0 }, 0, 0, VE, .unit = "level" }, 1234 { "V1", "Level Version 1", 1235 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version1 }, 0, 0, VE, .unit = "level" }, 1236 { "V2", "Level Version 2", 1237 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version2 }, 0, 0, VE, .unit = "level" }, 1238 { "V3", "Level Version 3", 1239 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version3 }, 0, 0, VE, .unit = "level" }, 1240 { NULL, } 1241 }; 1242 1243 DECLARE_MEDIACODEC_ENCODER(vp8, "VP8", AV_CODEC_ID_VP8) 1244 1245 #endif // CONFIG_VP8_MEDIACODEC_ENCODER 1246 1247 #if CONFIG_VP9_MEDIACODEC_ENCODER 1248 1249 enum MediaCodecVP9Level { 1250 VP9Level1 = 0x1, 1251 VP9Level11 = 0x2, 1252 VP9Level2 = 0x4, 1253 VP9Level21 = 0x8, 1254 VP9Level3 = 0x10, 1255 VP9Level31 = 0x20, 1256 VP9Level4 = 0x40, 1257 VP9Level41 = 0x80, 1258 VP9Level5 = 0x100, 1259 VP9Level51 = 0x200, 1260 VP9Level52 = 0x400, 1261 VP9Level6 = 0x800, 1262 VP9Level61 = 0x1000, 1263 VP9Level62 = 0x2000, 1264 }; 1265 1266 static const AVOption vp9_options[] = { 1267 COMMON_OPTION 1268 1269 FF_AVCTX_PROFILE_OPTION("profile0", NULL, VIDEO, AV_PROFILE_VP9_0) 1270 FF_AVCTX_PROFILE_OPTION("profile1", NULL, VIDEO, AV_PROFILE_VP9_1) 1271 FF_AVCTX_PROFILE_OPTION("profile2", NULL, VIDEO, AV_PROFILE_VP9_2) 1272 FF_AVCTX_PROFILE_OPTION("profile3", NULL, VIDEO, AV_PROFILE_VP9_3) 1273 1274 { "level", "Specify tier and level", 1275 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1276 { "1", "Level 1", 1277 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level1 }, 0, 0, VE, .unit = "level" }, 1278 { "1.1", "Level 1.1", 1279 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level11 }, 0, 0, VE, .unit = "level" }, 1280 { "2", "Level 2", 1281 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level2 }, 0, 0, VE, .unit = "level" }, 1282 { "2.1", "Level 2.1", 1283 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level21 }, 0, 0, VE, .unit = "level" }, 1284 { "3", "Level 3", 1285 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level3 }, 0, 0, VE, .unit = "level" }, 1286 { "3.1", "Level 3.1", 1287 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level31 }, 0, 0, VE, .unit = "level" }, 1288 { "4", "Level 4", 1289 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level4 }, 0, 0, VE, .unit = "level" }, 1290 { "4.1", "Level 4.1", 1291 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level41 }, 0, 0, VE, .unit = "level" }, 1292 { "5", "Level 5", 1293 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level5 }, 0, 0, VE, .unit = "level" }, 1294 { "5.1", "Level 5.1", 1295 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level51 }, 0, 0, VE, .unit = "level" }, 1296 { "5.2", "Level 5.2", 1297 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level52 }, 0, 0, VE, .unit = "level" }, 1298 { "6", "Level 6", 1299 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level6 }, 0, 0, VE, .unit = "level" }, 1300 { "6.1", "Level 4.1", 1301 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level61 }, 0, 0, VE, .unit = "level" }, 1302 { "6.2", "Level 6.2", 1303 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level62 }, 0, 0, VE, .unit = "level" }, 1304 { NULL, } 1305 }; 1306 1307 DECLARE_MEDIACODEC_ENCODER(vp9, "VP9", AV_CODEC_ID_VP9) 1308 1309 #endif // CONFIG_VP9_MEDIACODEC_ENCODER 1310 1311 #if CONFIG_MPEG4_MEDIACODEC_ENCODER 1312 1313 enum MediaCodecMpeg4Level { 1314 MPEG4Level0 = 0x01, 1315 MPEG4Level0b = 0x02, 1316 MPEG4Level1 = 0x04, 1317 MPEG4Level2 = 0x08, 1318 MPEG4Level3 = 0x10, 1319 MPEG4Level3b = 0x18, 1320 MPEG4Level4 = 0x20, 1321 MPEG4Level4a = 0x40, 1322 MPEG4Level5 = 0x80, 1323 MPEG4Level6 = 0x100, 1324 }; 1325 1326 static const AVOption mpeg4_options[] = { 1327 COMMON_OPTION 1328 1329 FF_MPEG4_PROFILE_OPTS 1330 1331 { "level", "Specify tier and level", 1332 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1333 { "0", "Level 0", 1334 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0 }, 0, 0, VE, .unit = "level" }, 1335 { "0b", "Level 0b", 1336 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0b }, 0, 0, VE, .unit = "level" }, 1337 { "1", "Level 1", 1338 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level1 }, 0, 0, VE, .unit = "level" }, 1339 { "2", "Level 2", 1340 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level2 }, 0, 0, VE, .unit = "level" }, 1341 { "3", "Level 3", 1342 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3 }, 0, 0, VE, .unit = "level" }, 1343 { "3b", "Level 3b", 1344 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3b }, 0, 0, VE, .unit = "level" }, 1345 { "4", "Level 4", 1346 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4 }, 0, 0, VE, .unit = "level" }, 1347 { "4a", "Level 4a", 1348 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4a }, 0, 0, VE, .unit = "level" }, 1349 { "5", "Level 5", 1350 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level5 }, 0, 0, VE, .unit = "level" }, 1351 { "6", "Level 6", 1352 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level6 }, 0, 0, VE, .unit = "level" }, 1353 { NULL, } 1354 }; 1355 1356 DECLARE_MEDIACODEC_ENCODER(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4) 1357 1358 #endif // CONFIG_MPEG4_MEDIACODEC_ENCODER 1359 1360 #if CONFIG_AV1_MEDIACODEC_ENCODER 1361 1362 enum MediaCodecAV1Level { 1363 AV1Level2 = 0x1, 1364 AV1Level21 = 0x2, 1365 AV1Level22 = 0x4, 1366 AV1Level23 = 0x8, 1367 AV1Level3 = 0x10, 1368 AV1Level31 = 0x20, 1369 AV1Level32 = 0x40, 1370 AV1Level33 = 0x80, 1371 AV1Level4 = 0x100, 1372 AV1Level41 = 0x200, 1373 AV1Level42 = 0x400, 1374 AV1Level43 = 0x800, 1375 AV1Level5 = 0x1000, 1376 AV1Level51 = 0x2000, 1377 AV1Level52 = 0x4000, 1378 AV1Level53 = 0x8000, 1379 AV1Level6 = 0x10000, 1380 AV1Level61 = 0x20000, 1381 AV1Level62 = 0x40000, 1382 AV1Level63 = 0x80000, 1383 AV1Level7 = 0x100000, 1384 AV1Level71 = 0x200000, 1385 AV1Level72 = 0x400000, 1386 AV1Level73 = 0x800000, 1387 }; 1388 1389 static const AVOption av1_options[] = { 1390 COMMON_OPTION 1391 1392 FF_AV1_PROFILE_OPTS 1393 1394 { "level", "Specify tier and level", 1395 OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" }, 1396 { "2", "Level 2", 1397 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level2 }, 0, 0, VE, .unit = "level" }, 1398 { "2.1", "Level 2.1", 1399 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level21 }, 0, 0, VE, .unit = "level" }, 1400 { "2.2", "Level 2.2", 1401 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level22 }, 0, 0, VE, .unit = "level" }, 1402 { "2.3", "Level 2.3", 1403 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level23 }, 0, 0, VE, .unit = "level" }, 1404 { "3", "Level 3", 1405 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level3 }, 0, 0, VE, .unit = "level" }, 1406 { "3.1", "Level 3.1", 1407 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level31 }, 0, 0, VE, .unit = "level" }, 1408 { "3.2", "Level 3.2", 1409 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level32 }, 0, 0, VE, .unit = "level" }, 1410 { "3.3", "Level 3.3", 1411 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level33 }, 0, 0, VE, .unit = "level" }, 1412 { "4", "Level 4", 1413 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level4 }, 0, 0, VE, .unit = "level" }, 1414 { "4.1", "Level 4.1", 1415 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level41 }, 0, 0, VE, .unit = "level" }, 1416 { "4.2", "Level 4.2", 1417 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level42 }, 0, 0, VE, .unit = "level" }, 1418 { "4.3", "Level 4.3", 1419 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level43 }, 0, 0, VE, .unit = "level" }, 1420 { "5", "Level 5", 1421 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level5 }, 0, 0, VE, .unit = "level" }, 1422 { "5.1", "Level 5.1", 1423 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level51 }, 0, 0, VE, .unit = "level" }, 1424 { "5.2", "Level 5.2", 1425 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level52 }, 0, 0, VE, .unit = "level" }, 1426 { "5.3", "Level 5.3", 1427 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level53 }, 0, 0, VE, .unit = "level" }, 1428 { "6", "Level 6", 1429 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level6 }, 0, 0, VE, .unit = "level" }, 1430 { "6.1", "Level 6.1", 1431 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level61 }, 0, 0, VE, .unit = "level" }, 1432 { "6.2", "Level 6.2", 1433 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level62 }, 0, 0, VE, .unit = "level" }, 1434 { "6.3", "Level 6.3", 1435 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level63 }, 0, 0, VE, .unit = "level" }, 1436 { "7", "Level 7", 1437 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level7 }, 0, 0, VE, .unit = "level" }, 1438 { "7.1", "Level 7.1", 1439 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level71 }, 0, 0, VE, .unit = "level" }, 1440 { "7.2", "Level 7.2", 1441 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level72 }, 0, 0, VE, .unit = "level" }, 1442 { "7.3", "Level 7.3", 1443 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level73 }, 0, 0, VE, .unit = "level" }, 1444 { NULL, } 1445 }; 1446 1447 DECLARE_MEDIACODEC_ENCODER(av1, "AV1", AV_CODEC_ID_AV1) 1448 1449 #endif // CONFIG_AV1_MEDIACODEC_ENCODER