21#include "config_components.h"
24#include <multimedia/player_framework/native_avcapability.h>
25#include <multimedia/player_framework/native_avcodec_videodecoder.h>
77#define OFFSET(x) offsetof(OHCodecDecContext, x)
90 OH_AVCodec **decp = obj;
91 OH_AVErrCode err = OH_VideoDecoder_Destroy(*decp);
101 const char *
name =
s->name;
107 OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(mime,
false, HARDWARE);
114 "Failed to get hardware codec %s, try software backend\n", mime);
115 cap = OH_AVCodec_GetCapabilityByCategory(mime,
false, SOFTWARE);
121 name = OH_AVCapability_GetName(cap);
126 s->dec = OH_VideoDecoder_CreateByName(
name);
139 *
s->dec_ref =
s->dec;
154 s->output_to_window =
true;
163 "Invalid width/height (%dx%d), width and height are mandatory for ohcodec\n",
168 OH_AVFormat *
format = OH_AVFormat_Create();
172 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_WIDTH, avctx->
width);
173 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_HEIGHT, avctx->
height);
174 if (!
s->output_to_window)
175 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_PIXEL_FORMAT,
176 AV_PIXEL_FORMAT_NV12);
178 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_PIXEL_FORMAT,
179 AV_PIXEL_FORMAT_SURFACE_FORMAT);
180 OH_AVErrCode err = OH_VideoDecoder_Configure(
s->dec,
format);
181 OH_AVFormat_Destroy(
format);
182 if (err != AV_ERR_OK) {
189 if (
s->output_to_window) {
190 err = OH_VideoDecoder_SetSurface(
s->dec,
window);
191 if (err != AV_ERR_OK) {
227 if (!OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_PIC_WIDTH, &
s->width) ||
228 !OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &
s->height) ||
229 !OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_STRIDE, &
s->stride) ||
230 !OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_SLICE_HEIGHT,
239 if (
s->stride <= 0 ||
s->slice_height <= 0) {
241 "Buffer stride (%d) or slice height (%d) is invalid\n",
242 s->stride,
s->slice_height);
246 if (OH_AVFormat_GetIntValue(
format, OH_MD_KEY_PIXEL_FORMAT, &n)) {
252 if (
s->output_to_window)
267 if (OH_AVFormat_GetIntValue(
format,
268 OH_MD_KEY_MATRIX_COEFFICIENTS,
271 if (OH_AVFormat_GetIntValue(
format,
272 OH_MD_KEY_COLOR_PRIMARIES,
275 if (OH_AVFormat_GetIntValue(
format,
276 OH_MD_KEY_TRANSFER_CHARACTERISTICS,
279 if (OH_AVFormat_GetIntValue(
format,
280 OH_MD_KEY_RANGE_FLAG,
284 if (OH_AVFormat_GetDoubleValue(
format, OH_MD_KEY_VIDEO_SAR, &d)) {
289 s->got_stream_info =
true;
294 OH_AVFormat_DumpInfo(
format));
299 OH_AVBuffer *
buffer,
void *userdata)
318 OH_AVBuffer *
buffer,
void *userdata)
340 OH_AVCodecCallback
cb = {
347 err = OH_VideoDecoder_RegisterCallback(
s->dec,
cb, avctx);
348 if (err != AV_ERR_OK) {
354 err = OH_VideoDecoder_Prepare(
s->dec);
355 if (err != AV_ERR_OK) {
361 err = OH_VideoDecoder_Start(
s->dec);
362 if (err != AV_ERR_OK) {
393 if (!
s->input_queue || !
s->output_queue)
411 OH_AVErrCode err = OH_VideoDecoder_Stop(
s->dec);
412 if (err == AV_ERR_OK)
440 OH_AVCodec *dec = *
buffer->dec_ref;
441 OH_AVCodecBufferAttr attr;
442 OH_AVErrCode err = OH_AVBuffer_GetBufferAttr(
buffer->buffer, &attr);
443 if (err == AV_ERR_OK && !(attr.flags & AVCODEC_BUFFER_FLAGS_DISCARD))
444 OH_VideoDecoder_RenderOutputBuffer(dec,
buffer->index);
446 OH_VideoDecoder_FreeOutputBuffer(dec,
buffer->index);
455 const OH_AVCodecBufferAttr *attr)
460 frame->height =
s->height;
477 if (!
frame->buf[0]) {
491 const OH_AVCodecBufferAttr *attr)
497 frame->height =
s->height;
505 uint8_t *p = OH_AVBuffer_GetAddr(output->
buffer);
511 uint8_t *
src[4] = {0};
512 int src_linesizes[4] = {0};
524 OH_AVErrCode err = OH_VideoDecoder_FreeOutputBuffer(
s->dec, output->
index);
525 if (err != AV_ERR_OK) {
539 OH_AVCodecBufferAttr attr;
541 OH_AVErrCode err = OH_AVBuffer_GetBufferAttr(output->
buffer, &attr);
542 if (err != AV_ERR_OK)
545 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
547 OH_VideoDecoder_FreeOutputBuffer(
s->dec, output->
index);
551 if (!
s->got_stream_info) {
554 "decoder didn't notify stream info, try get format explicitly\n");
556 OH_AVFormat *
format = OH_VideoDecoder_GetOutputDescription(
s->dec);
563 OH_AVFormat_Destroy(
format);
564 if (!
s->got_stream_info)
568 if (
s->output_to_window)
579 if (!
s->pkt.size && !
s->eof_sent) {
580 OH_AVCodecBufferAttr attr = {
581 .flags = AVCODEC_BUFFER_FLAGS_EOS,
583 err = OH_AVBuffer_SetBufferAttr(input->
buffer, &attr);
584 if (err != AV_ERR_OK)
586 err = OH_VideoDecoder_PushInputBuffer(
s->dec, input->
index);
587 if (err != AV_ERR_OK)
593 uint8_t *p = OH_AVBuffer_GetAddr(input->
buffer);
597 "Failed to get buffer addr (%p) or capacity (%d)\n",
601 n =
FFMIN(
s->pkt.size, n);
602 memcpy(p,
s->pkt.data, n);
604 OH_AVCodecBufferAttr attr = {
610 ? AVCODEC_BUFFER_FLAGS_SYNC_FRAME : 0,
613 err = OH_AVBuffer_SetBufferAttr(input->
buffer, &attr);
614 if (err != AV_ERR_OK) {
618 err = OH_VideoDecoder_PushInputBuffer(
s->dec, input->
index);
619 if (err != AV_ERR_OK) {
626 if (n < s->
pkt.size) {
646 while (!
s->decode_status) {
650 if (
s->eof_sent && !
s->decode_status)
656 ret =
s->decode_status;
674 while (!
s->decode_status) {
680 ret =
s->decode_status;
698 OH_VideoDecoder_Flush(
s->dec);
704 s->decode_status = 0;
709 OH_VideoDecoder_Start(
s->dec);
725#define VD (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM)
727 {
"codec_name",
"Select codec by name",
729 {
"allow_sw",
"Allow software decoding",
734#define DECLARE_OHCODEC_VCLASS(short_name) \
735 static const AVClass short_name##_oh_dec_class = { \
736 .class_name = #short_name "_ohcodec", \
737 .item_name = av_default_item_name, \
738 .option = ohcodec_vdec_options, \
739 .version = LIBAVUTIL_VERSION_INT, \
742#define DECLARE_OHCODEC_VDEC(short_name, full_name, codec_id, bsf) \
743 DECLARE_OHCODEC_VCLASS(short_name) \
744 const FFCodec ff_##short_name##_oh_decoder = { \
745 .p.name = #short_name "_ohcodec", \
746 CODEC_LONG_NAME(full_name " OpenHarmony Codec"), \
747 .p.type = AVMEDIA_TYPE_VIDEO, \
749 .p.priv_class = &short_name##_oh_dec_class, \
750 .priv_data_size = sizeof(OHCodecDecContext), \
751 .init = oh_decode_init, \
752 FF_CODEC_RECEIVE_FRAME_CB(oh_decode_receive_frame), \
753 .flush = oh_decode_flush, \
754 .close = oh_decode_close, \
755 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | \
756 AV_CODEC_CAP_HARDWARE, \
757 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \
759 .hw_configs = oh_hw_configs, \
760 .p.wrapper_name = "ohcodec", \
763#if CONFIG_H264_OH_DECODER
767#if CONFIG_HEVC_OH_DECODER
static const char *const format[]
Libavcodec external API header.
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
Set various frame properties from the codec context / packet data.
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
int ff_set_sar(AVCodecContext *avctx, AVRational sar)
Check that the provided sample aspect ratio is valid and set it on the codec context.
int ff_set_dimensions(AVCodecContext *s, int width, int height)
static SDL_Window * window
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
@ AV_CODEC_HW_CONFIG_METHOD_AD_HOC
The codec supports this format by some ad-hoc method.
@ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
The codec supports this format via the hw_device_ctx interface.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
#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_EXTERNAL
Generic error in an external library.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AVERROR_EOF
End of file.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
void av_fifo_reset2(AVFifo *f)
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, uint8_t *ptr, const int linesizes[4])
Fill plane data pointers for an image with pixel format pix_fmt and height height.
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
@ AV_HWDEVICE_TYPE_OHCODEC
av_cold void ff_pthread_free(void *obj, const unsigned offsets[])
av_cold int ff_pthread_init(void *obj, const unsigned offsets[])
Initialize/destroy a list of mutexes/conditions contained in a structure.
static int ff_cond_wait(AVCond *cond, AVMutex *mutex)
static int ff_mutex_unlock(AVMutex *mutex)
static int ff_mutex_lock(AVMutex *mutex)
static int ff_cond_signal(AVCond *cond)
Memory handling functions.
enum AVPixelFormat ff_oh_pix_to_ff_pix(OH_AVPixelFormat oh_pix)
int ff_oh_err_to_ff_err(OH_AVErrCode err)
static const char * ff_oh_mime(enum AVCodecID codec_id, void *log)
static av_cold int oh_decode_init(AVCodecContext *avctx)
#define DECLARE_OHCODEC_VDEC(short_name, full_name, codec_id, bsf)
static void oh_decode_on_need_input(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
static void oh_decode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
static int oh_decode_wrap_sw_buffer(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output, const OH_AVCodecBufferAttr *attr)
static void oh_decode_release(AVRefStructOpaque unused, void *obj)
static int oh_decode_set_format(OHCodecDecContext *s, AVCodecContext *avctx)
static int oh_decode_wrap_hw_buffer(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output, const OH_AVCodecBufferAttr *attr)
static int oh_decode_start(OHCodecDecContext *s, AVCodecContext *avctx)
static int oh_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame)
static const AVCodecHWConfigInternal *const oh_hw_configs[]
static int oh_decode_output_frame(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output)
static int oh_decode_create(OHCodecDecContext *s, AVCodecContext *avctx)
static void oh_decode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format, void *userdata)
static void oh_decode_flush(AVCodecContext *avctx)
static void oh_buffer_release(void *opaque, uint8_t *data)
static const AVOption ohcodec_vdec_options[]
static void oh_decode_on_output(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
static int oh_decode_send_pkt(AVCodecContext *avctx, OHBufferQueueItem *input)
static av_cold int oh_decode_close(AVCodecContext *avctx)
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
@ AVCOL_RANGE_JPEG
Full range content.
#define DEFINE_OFFSET_ARRAY(type, name, cnt_variable, mutexes, conds)
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.
uint8_t * data
The 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.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
enum AVColorSpace colorspace
YUV colorspace type.
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
This structure describes decoded (raw) audio or video data.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
OpenHarmony codec device.
void * native_window
Pointer to OHNativeWindow.
This structure stores compressed data.
Rational number (pair of numerator and denominator).
OH_AVCodec ** dec_ref
RefStruct reference.
RefStruct is an API for creating reference-counted objects with minimal overhead.
static double cb(void *priv, double x, double y)