diff options
author | Rick Kern <kernrj@gmail.com> | 2019-05-12 16:05:51 -0400 |
---|---|---|
committer | Rick Kern <rick@8birdsvideo.com> | 2019-05-12 16:30:11 -0400 |
commit | 98478c05edb674ec429c298fbe593bda493ba60f (patch) | |
tree | d0bcb36ee92a705c64cf89c8742ed602ce2c7189 | |
parent | 714c8b0766244f1a304fe05a9489929118787f58 (diff) | |
download | ffmpeg-98478c05edb674ec429c298fbe593bda493ba60f.tar.gz |
lavc/videotoolboxenc: Add support for 10-bit HEVC encoding.
Hardware-accelerated encoding may not support 10-bit encoding. Use
'-require_sw 1' in this case.
Fixes: #7581
Signed-off-by: Rick Kern <kernrj@gmail.com>
-rw-r--r-- | libavcodec/videotoolboxenc.c | 102 |
1 files changed, 56 insertions, 46 deletions
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index f501ee6746..3665581283 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -762,6 +762,11 @@ static int get_cv_pixel_format(AVCodecContext* avctx, *av_pixel_format = range == AVCOL_RANGE_JPEG ? kCVPixelFormatType_420YpCbCr8PlanarFullRange : kCVPixelFormatType_420YpCbCr8Planar; + } else if (fmt == AV_PIX_FMT_P010LE) { + *av_pixel_format = range == AVCOL_RANGE_JPEG ? + kCVPixelFormatType_420YpCbCr10BiPlanarFullRange : + kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; + *av_pixel_format = kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; } else { return AVERROR(EINVAL); } @@ -1986,6 +1991,17 @@ static int get_cv_pixel_info( strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2; break; + case AV_PIX_FMT_P010LE: + *plane_count = 2; + widths[0] = avctx->width; + heights[0] = avctx->height; + strides[0] = frame ? frame->linesize[0] : (avctx->width * 2 + 63) & -64; + + widths[1] = (avctx->width + 1) / 2; + heights[1] = (avctx->height + 1) / 2; + strides[1] = frame ? frame->linesize[1] : ((avctx->width + 1) / 2 + 63) & -64; + break; + default: av_log( avctx, @@ -2348,21 +2364,11 @@ static int vtenc_populate_extradata(AVCodecContext *avctx, CFDictionaryRef pixel_buffer_info) { VTEncContext *vtctx = avctx->priv_data; - AVFrame *frame = av_frame_alloc(); - int y_size = avctx->width * avctx->height; - int chroma_size = (avctx->width / 2) * (avctx->height / 2); - CMSampleBufferRef buf = NULL; int status; - - if (!frame) - return AVERROR(ENOMEM); - - frame->buf[0] = av_buffer_alloc(y_size + 2 * chroma_size); - - if(!frame->buf[0]){ - status = AVERROR(ENOMEM); - goto pe_cleanup; - } + CVPixelBufferPoolRef pool = NULL; + CVPixelBufferRef pix_buf = NULL; + CMTime time; + CMSampleBufferRef buf = NULL; status = vtenc_create_encoder(avctx, codec_type, @@ -2374,39 +2380,38 @@ static int vtenc_populate_extradata(AVCodecContext *avctx, if (status) goto pe_cleanup; - frame->data[0] = frame->buf[0]->data; - memset(frame->data[0], 0, y_size); - - frame->data[1] = frame->buf[0]->data + y_size; - memset(frame->data[1], 128, chroma_size); - - - if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { - frame->data[2] = frame->buf[0]->data + y_size + chroma_size; - memset(frame->data[2], 128, chroma_size); + pool = VTCompressionSessionGetPixelBufferPool(vtctx->session); + if(!pool){ + av_log(avctx, AV_LOG_ERROR, "Error getting pixel buffer pool.\n"); + goto pe_cleanup; } - frame->linesize[0] = avctx->width; + status = CVPixelBufferPoolCreatePixelBuffer(NULL, + pool, + &pix_buf); - if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { - frame->linesize[1] = - frame->linesize[2] = (avctx->width + 1) / 2; - } else { - frame->linesize[1] = (avctx->width + 1) / 2; + if(status != kCVReturnSuccess){ + av_log(avctx, AV_LOG_ERROR, "Error creating frame from pool: %d\n", status); + goto pe_cleanup; } - frame->format = avctx->pix_fmt; - frame->width = avctx->width; - frame->height = avctx->height; - frame->colorspace = avctx->colorspace; - frame->color_range = avctx->color_range; - frame->color_trc = avctx->color_trc; - frame->color_primaries = avctx->color_primaries; + unsigned pbuftype = CVPixelBufferGetPixelFormatType(pix_buf); + + time = CMTimeMake(0, avctx->time_base.den); + status = VTCompressionSessionEncodeFrame(vtctx->session, + pix_buf, + time, + kCMTimeInvalid, + NULL, + NULL, + NULL); - frame->pts = 0; - status = vtenc_send_frame(avctx, vtctx, frame); if (status) { - av_log(avctx, AV_LOG_ERROR, "Error sending frame: %d\n", status); + av_log(avctx, + AV_LOG_ERROR, + "Error sending frame for extradata: %d\n", + status); + goto pe_cleanup; } @@ -2434,9 +2439,6 @@ pe_cleanup: vtctx->session = NULL; vtctx->frame_ct_out = 0; - av_frame_unref(frame); - av_frame_free(&frame); - av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0)); return status; @@ -2475,10 +2477,18 @@ static av_cold int vtenc_close(AVCodecContext *avctx) return 0; } -static const enum AVPixelFormat pix_fmts[] = { +static const enum AVPixelFormat avc_pix_fmts[] = { + AV_PIX_FMT_VIDEOTOOLBOX, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat hevc_pix_fmts[] = { AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_P010LE, AV_PIX_FMT_NONE }; @@ -2539,7 +2549,7 @@ AVCodec ff_h264_videotoolbox_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .priv_data_size = sizeof(VTEncContext), - .pix_fmts = pix_fmts, + .pix_fmts = avc_pix_fmts, .init = vtenc_init, .encode2 = vtenc_frame, .close = vtenc_close, @@ -2571,7 +2581,7 @@ AVCodec ff_hevc_videotoolbox_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(VTEncContext), - .pix_fmts = pix_fmts, + .pix_fmts = hevc_pix_fmts, .init = vtenc_init, .encode2 = vtenc_frame, .close = vtenc_close, |