int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, int dpb_size) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; const AVPixFmtDescriptor *sw_desc; int cuvid_codec_type, cuvid_chroma_format; sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!sw_desc) return AVERROR_BUG; cuvid_codec_type = map_avcodec_id(avctx->codec_id); if (cuvid_codec_type < 0) { av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n"); return AVERROR_BUG; } cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt); if (cuvid_chroma_format < 0) { av_log(avctx, AV_LOG_VERBOSE, "Unsupported chroma format\n"); return AVERROR(EINVAL); } frames_ctx->format = AV_PIX_FMT_CUDA; frames_ctx->width = (avctx->coded_width + 1) & ~1; frames_ctx->height = (avctx->coded_height + 1) & ~1; /* * We add two extra frames to the pool to account for deinterlacing filters * holding onto their frames. */ frames_ctx->initial_pool_size = dpb_size + 2; frames_ctx->free = nvdec_free_dummy; frames_ctx->pool = av_buffer_pool_init(0, nvdec_alloc_dummy); if (!frames_ctx->pool) return AVERROR(ENOMEM); switch (sw_desc->comp[0].depth) { case 8: frames_ctx->sw_format = AV_PIX_FMT_NV12; break; case 10: frames_ctx->sw_format = AV_PIX_FMT_P010; break; case 12: frames_ctx->sw_format = AV_PIX_FMT_P016; break; default: return AVERROR(EINVAL); } return 0; }
static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) { FramePool *pool = avctx->internal->pool; int i, ret; switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: { uint8_t *data[4]; int linesize[4]; int size[4] = { 0 }; int w = frame->width; int h = frame->height; int tmpsize, unaligned; if (pool->format == frame->format && pool->width == frame->width && pool->height == frame->height) return 0; avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); do { // NOTE: do not align linesizes individually, this breaks e.g. assumptions // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 av_image_fill_linesizes(linesize, avctx->pix_fmt, w); // increase alignment of w for next try (rhs gives the lowest bit set in w) w += w & ~(w - 1); unaligned = 0; for (i = 0; i < 4; i++) unaligned |= linesize[i] % pool->stride_align[i]; } while (unaligned); tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h, NULL, linesize); if (tmpsize < 0) return -1; for (i = 0; i < 3 && data[i + 1]; i++) size[i] = data[i + 1] - data[i]; size[i] = tmpsize - (data[i] - data[0]); for (i = 0; i < 4; i++) { av_buffer_pool_uninit(&pool->pools[i]); pool->linesize[i] = linesize[i]; if (size[i]) { pool->pools[i] = av_buffer_pool_init(size[i] + 16, NULL); if (!pool->pools[i]) { ret = AVERROR(ENOMEM); goto fail; } } } pool->format = frame->format; pool->width = frame->width; pool->height = frame->height; break; } case AVMEDIA_TYPE_AUDIO: { int ch = av_get_channel_layout_nb_channels(frame->channel_layout); int planar = av_sample_fmt_is_planar(frame->format); int planes = planar ? ch : 1; if (pool->format == frame->format && pool->planes == planes && pool->channels == ch && frame->nb_samples == pool->samples) return 0; av_buffer_pool_uninit(&pool->pools[0]); ret = av_samples_get_buffer_size(&pool->linesize[0], ch, frame->nb_samples, frame->format, 0); if (ret < 0) goto fail; pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL); if (!pool->pools[0]) { ret = AVERROR(ENOMEM); goto fail; } pool->format = frame->format; pool->planes = planes; pool->channels = ch; pool->samples = frame->nb_samples; break; } default: av_assert0(0); } return 0; fail: for (i = 0; i < 4; i++) av_buffer_pool_uninit(&pool->pools[i]); pool->format = -1; pool->planes = pool->channels = pool->samples = 0; pool->width = pool->height = 0; return ret; }
FFVideoFramePool *ff_video_frame_pool_init(AVBufferRef* (*alloc)(int size), int width, int height, enum AVPixelFormat format, int align) { int i, ret; FFVideoFramePool *pool; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); if (!desc) return NULL; pool = av_mallocz(sizeof(FFVideoFramePool)); if (!pool) return NULL; pool->width = width; pool->height = height; pool->format = format; pool->align = align; if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) { goto fail; } if (!pool->linesize[0]) { for(i = 1; i <= align; i += i) { ret = av_image_fill_linesizes(pool->linesize, pool->format, FFALIGN(pool->width, i)); if (ret < 0) { goto fail; } if (!(pool->linesize[0] & (pool->align - 1))) break; } for (i = 0; i < 4 && pool->linesize[i]; i++) { pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); } } for (i = 0; i < 4 && pool->linesize[i]; i++) { int h = FFALIGN(pool->height, 32); if (i == 1 || i == 2) h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); pool->pools[i] = av_buffer_pool_init(pool->linesize[i] * h + 16 + 16 - 1, alloc); if (!pool->pools[i]) goto fail; } if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { pool->pools[1] = av_buffer_pool_init(AVPALETTE_SIZE, alloc); if (!pool->pools[1]) goto fail; } return pool; fail: ff_video_frame_pool_uninit(&pool); return NULL; }