#ifndef OWNED_NV12_FRAME_H #define OWNED_NV12_FRAME_H extern "C" { #include } #include #include using RamInputRelease = void (*)(void *, uint8_t *); struct RamFrameDeleter { void operator()(AVFrame *frame) const { av_frame_free(&frame); } }; using RamOwnedFrame = std::unique_ptr; static RamOwnedFrame make_owned_nv12_frame(const uint8_t *data, int length, int width, int height, void *owner, RamInputRelease release) { const int64_t pixels = static_cast(width) * height; if (!data || !release || width <= 0 || height <= 0 || width % 2 || height % 2 || pixels > std::numeric_limits::max() / 3 * 2 || length < pixels + pixels / 2) { if (release) release(owner, const_cast(data)); return RamOwnedFrame(); } RamOwnedFrame frame(av_frame_alloc()); if (!frame) { release(owner, const_cast(data)); return frame; } frame->buf[0] = av_buffer_create(const_cast(data), length, release, owner, AV_BUFFER_FLAG_READONLY); if (!frame->buf[0]) { release(owner, const_cast(data)); return RamOwnedFrame(); } frame->format = AV_PIX_FMT_NV12; frame->width = width; frame->height = height; frame->data[0] = frame->buf[0]->data; frame->data[1] = frame->data[0] + pixels; frame->linesize[0] = width; frame->linesize[1] = width; return frame; } #endif