22#include <drm_fourcc.h>
24#include <rockchip/mpp_buffer.h>
25#include <rockchip/rk_mpi.h>
44#define RECEIVE_FRAME_TIMEOUT 100
45#define FRAMEGROUP_MAX_FRAMES 16
46#define INPUT_MAX_PACKETS 4
77 default:
return MPP_VIDEO_CodingUnused;
84 case MPP_FMT_YUV420SP:
return DRM_FORMAT_NV12;
85#ifdef DRM_FORMAT_NV12_10
86 case MPP_FMT_YUV420SP_10BIT:
return DRM_FORMAT_NV12_10;
106 mpp_packet_set_pts(packet,
pts);
109 mpp_packet_set_eos(packet);
113 if (ret == MPP_ERR_BUFFER_FULL) {
122 mpp_packet_deinit(&packet);
145 mpp_buffer_group_put(
decoder->frame_group);
157 MppCodingType codectype = MPP_VIDEO_CodingUnused;
176 if (codectype == MPP_VIDEO_CodingUnused) {
182 ret = mpp_check_support_format(MPP_CTX_DEC, codectype);
198 ret = mpp_init(
decoder->ctx, MPP_CTX_DEC, codectype);
206 paramS32 = MPP_POLL_BLOCK;
207 ret =
decoder->mpi->control(
decoder->ctx, MPP_SET_OUTPUT_BLOCK, ¶mS32);
209 av_log(avctx,
AV_LOG_ERROR,
"Failed to set blocking mode on MPI (code = %d).\n", ret);
215 ret =
decoder->mpi->control(
decoder->ctx, MPP_SET_OUTPUT_BLOCK_TIMEOUT, ¶mS64);
217 av_log(avctx,
AV_LOG_ERROR,
"Failed to set block timeout on MPI (code = %d).\n", ret);
222 ret = mpp_buffer_group_get_internal(&
decoder->frame_group, MPP_BUFFER_TYPE_ION);
282 const uint8_t *extradata;
288 av_log(avctx,
AV_LOG_ERROR,
"Failed to write extradata to decoder (code = %d)\n", ret);
297 if (ret && ret!=
AVERROR(EAGAIN))
308 mpp_frame_deinit(&framecontext->
frame);
319 MppFrame mppframe =
NULL;
323 MppFrameFormat mppformat;
327 if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
334 if (mpp_frame_get_info_change(mppframe)) {
337 av_log(avctx,
AV_LOG_INFO,
"Decoder noticed an info change (%dx%d), format=%d\n",
338 (
int)mpp_frame_get_width(mppframe), (
int)mpp_frame_get_height(mppframe),
339 (
int)mpp_frame_get_fmt(mppframe));
341 avctx->
width = mpp_frame_get_width(mppframe);
342 avctx->
height = mpp_frame_get_height(mppframe);
354 mppformat = mpp_frame_get_fmt(mppframe);
369 }
else if (mpp_frame_get_eos(mppframe)) {
374 }
else if (mpp_frame_get_discard(mppframe)) {
378 }
else if (mpp_frame_get_errinfo(mppframe)) {
389 frame->width = mpp_frame_get_width(mppframe);
390 frame->height = mpp_frame_get_height(mppframe);
391 frame->pts = mpp_frame_get_pts(mppframe);
392 frame->color_range = mpp_frame_get_color_range(mppframe);
393 frame->color_primaries = mpp_frame_get_color_primaries(mppframe);
394 frame->color_trc = mpp_frame_get_color_trc(mppframe);
395 frame->colorspace = mpp_frame_get_colorspace(mppframe);
397 mode = mpp_frame_get_mode(mppframe);
398 if ((
mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED)
400 if ((
mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST)
403 mppformat = mpp_frame_get_fmt(mppframe);
407 buffer = mpp_frame_get_buffer(mppframe);
417 } *combined_desc =
av_mallocz(
sizeof(*combined_desc));
418 if (!combined_desc) {
422 desc = &combined_desc->desc;
423 framecontext = &combined_desc->framecontext;
425 desc->nb_objects = 1;
426 desc->objects[0].fd = mpp_buffer_get_fd(
buffer);
427 desc->objects[0].size = mpp_buffer_get_size(
buffer);
430 layer = &
desc->layers[0];
431 layer->
format = drmformat;
436 layer->
planes[0].
pitch = mpp_frame_get_hor_stride(mppframe);
443 framecontext->
frame = mppframe;
449 if (!
frame->buf[0]) {
457 if (!
frame->hw_frames_ctx) {
464 av_log(avctx,
AV_LOG_ERROR,
"Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret);
465 mpp_frame_deinit(&mppframe);
467 }
else if (
decoder->eos_reached) {
469 }
else if (ret == MPP_ERR_TIMEOUT) {
477 mpp_frame_deinit(&mppframe);
487 RK_S32 usedslots, freeslots;
491 ret =
decoder->mpi->control(
decoder->ctx, MPP_DEC_GET_STREAM_COUNT, &usedslots);
509 if (ret < 0 && ret !=
AVERROR(EAGAIN)) {
513 }
else if (ret ==
AVERROR(EAGAIN)) {
522 if (freeslots > 1 && !
decoder->eos_reached)
553#define RKMPP_DEC_CLASS(NAME) \
554 static const AVClass rkmpp_##NAME##_dec_class = { \
555 .class_name = "rkmpp_" #NAME "_dec", \
556 .version = LIBAVUTIL_VERSION_INT, \
559#define RKMPP_DEC(NAME, ID, BSFS) \
560 RKMPP_DEC_CLASS(NAME) \
561 const FFCodec ff_##NAME##_rkmpp_decoder = { \
562 .p.name = #NAME "_rkmpp", \
563 CODEC_LONG_NAME(#NAME " (rkmpp)"), \
564 .p.type = AVMEDIA_TYPE_VIDEO, \
566 .priv_data_size = sizeof(RKMPPDecodeContext), \
567 .init = rkmpp_init_decoder, \
568 .close = rkmpp_close_decoder, \
569 FF_CODEC_RECEIVE_FRAME_CB(rkmpp_receive_frame), \
570 .flush = rkmpp_flush, \
571 .p.priv_class = &rkmpp_##NAME##_dec_class, \
572 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
573 .hw_configs = rkmpp_hw_configs, \
575 .p.wrapper_name = "rkmpp", \
576 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_NOT_INIT_THREADSAFE, \
Libavcodec external API header.
refcounted data buffer API
common internal and external API header
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
static void ff_decode_get_extradata(const AVCodecContext *avctx, const uint8_t **extradata, int *extradata_size)
Helper function for decoders that may use a BSF that changes extradata.
reference-counted frame API
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EOF
End of file.
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define HW_CONFIG_INTERNAL(format)
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given hardware type.
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
API-specific header for AV_HWDEVICE_TYPE_DRM.
static const chunk_decoder decoder[8]
Memory handling functions.
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
static av_cold int rkmpp_close_decoder(AVCodecContext *avctx)
#define FRAMEGROUP_MAX_FRAMES
#define INPUT_MAX_PACKETS
static void rkmpp_release_frame(void *opaque, uint8_t *data)
static const AVCodecHWConfigInternal *const rkmpp_hw_configs[]
#define RECEIVE_FRAME_TIMEOUT
static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, int64_t pts)
#define RKMPP_DEC(NAME, ID, BSFS)
static void rkmpp_release_decoder(AVRefStructOpaque unused, void *obj)
static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
static av_cold int rkmpp_init_decoder(AVCodecContext *avctx)
static av_cold void rkmpp_flush(AVCodecContext *avctx)
static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
A reference to a data buffer.
Describe the class of an AVClass context structure.
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int width
picture width / height.
struct AVCodecInternal * internal
Private context used for internal data.
AVPacket * in_pkt
This packet is used to hold the packet given to decoders implementing the .decode API; it is unused b...
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
int nb_planes
Number of planes in the layer.
uint32_t format
Format of the layer (DRM_FORMAT_*).
ptrdiff_t pitch
Pitch (linesize) of this plane.
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor.
ptrdiff_t offset
Offset within that object of this plane.
This structure describes decoded (raw) audio or video data.
This struct describes a set or pool of "hardware" frames (i.e.
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int width
The allocated dimensions of the frames in this pool.
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
RKMPPDecoder * decoder
RefStruct reference.
MppBufferGroup frame_group
const RKMPPDecoder * decoder_ref
RefStruct reference.
RefStruct is an API for creating reference-counted objects with minimal overhead.