21#include "config_components.h"
24#include <multimedia/player_framework/native_avcapability.h>
25#include <multimedia/player_framework/native_avcodec_videoencoder.h>
26#include <native_window/external_window.h>
78 const char *
name =
s->name;
84 OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(mime,
true, HARDWARE);
91 "Failed to get hardware codec %s, try software backend\n", mime);
92 cap = OH_AVCodec_GetCapabilityByCategory(mime,
true, SOFTWARE);
98 name = OH_AVCapability_GetName(cap);
103 s->enc = OH_VideoEncoder_CreateByName(
name);
117 OH_AVFormat *
format = OH_AVFormat_Create();
121 bool b = OH_AVFormat_SetIntValue(
format, OH_MD_KEY_WIDTH, avctx->
width);
122 b =
b && OH_AVFormat_SetIntValue(
format, OH_MD_KEY_HEIGHT, avctx->
height);
130 OH_AVFormat_SetDoubleValue(
format, OH_MD_KEY_FRAME_RATE,
137 b = OH_AVFormat_SetIntValue(
format, OH_MD_KEY_PIXEL_FORMAT,
pix);
144 if (
s->bitrate_mode != -1) {
145 b = OH_AVFormat_SetIntValue(
format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE,
s->bitrate_mode);
153 OH_AVFormat_SetLongValue(
format, OH_MD_KEY_BITRATE, avctx->
bit_rate);
162 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_I_FRAME_INTERVAL, gop);
168 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_I_FRAME_INTERVAL, 0);
171 OH_AVFormat_SetIntValue(
format, OH_MD_KEY_I_FRAME_INTERVAL, -1);
174 OH_AVErrCode err = OH_VideoEncoder_Configure(
s->enc,
format);
175 if (err != AV_ERR_OK) {
185 "ohcodec can only export native window via hw device, "
186 "doesn't support import hw device\n");
191 err = OH_VideoEncoder_GetSurface(
s->enc, &
s->native_window);
192 if (err != AV_ERR_OK) {
211 OH_AVFormat_Destroy(
format);
238 if (!OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_STRIDE, &
s->stride))
240 if (!OH_AVFormat_GetIntValue(
format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &
s->slice_height))
241 s->slice_height = avctx->
height;
243 s->got_stream_info =
true;
247 OH_AVBuffer *
buffer,
void *userdata)
266 OH_AVBuffer *
buffer,
void *userdata)
288 OH_AVCodecCallback
cb = {
295 err = OH_VideoEncoder_RegisterCallback(
s->enc,
cb, avctx);
296 if (err != AV_ERR_OK) {
302 err = OH_VideoEncoder_Prepare(
s->enc);
303 if (err != AV_ERR_OK) {
309 err = OH_VideoEncoder_Start(
s->enc);
310 if (err != AV_ERR_OK) {
343 if (!
s->input_queue || !
s->output_queue || !
s->frame)
358 if (
s->native_window) {
359 OH_NativeWindow_DestroyNativeWindow(
s->native_window);
360 s->native_window =
NULL;
362 OH_VideoEncoder_Stop(
s->enc);
363 OH_AVErrCode err = OH_VideoEncoder_Destroy(
s->enc);
364 if (err == AV_ERR_OK)
391 OH_AVCodecBufferAttr attr;
394 OH_AVErrCode err = OH_AVBuffer_GetBufferAttr(output->
buffer, &attr);
395 if (err != AV_ERR_OK) {
399 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
405 p = OH_AVBuffer_GetAddr(output->
buffer);
411 if (attr.flags & AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
419 memcpy(
s->extradata, p + attr.offset, attr.size);
420 s->extradata_size = attr.size;
425 int64_t extradata_size =
s->extradata_size;
426 s->extradata_size = 0;
430 s->extradata, extradata_size);
442 memcpy(
pkt->data,
s->extradata, extradata_size);
444 memcpy(
pkt->data + extradata_size, p + attr.offset, attr.size);
446 if (attr.flags & AVCODEC_BUFFER_FLAGS_SYNC_FRAME)
450 OH_VideoEncoder_FreeOutputBuffer(
s->enc, output->
index);
461 if (
s->frame->buf[0]) {
466 OH_AVErrCode err = OH_VideoEncoder_NotifyEndOfStream(
s->enc);
478 if (!
s->got_stream_info) {
481 "decoder didn't notify stream info, try get format explicitly\n");
483 OH_AVFormat *
format = OH_VideoEncoder_GetOutputDescription(
s->enc);
490 OH_AVFormat_Destroy(
format);
491 if (!
s->got_stream_info)
495 if (!
frame->buf[0] && !
s->eof_sent) {
496 OH_AVCodecBufferAttr attr = {
497 .flags = AVCODEC_BUFFER_FLAGS_EOS,
499 err = OH_AVBuffer_SetBufferAttr(input->
buffer, &attr);
500 if (err != AV_ERR_OK)
502 err = OH_VideoEncoder_PushInputBuffer(
s->enc, input->
index);
503 if (err != AV_ERR_OK)
509 uint8_t *p = OH_AVBuffer_GetAddr(input->
buffer);
513 "Failed to get buffer addr (%p) or capacity (%d)\n",
518 uint8_t *
dst[4] = {0};
519 int dst_linesizes[4] = {0};
530 OH_AVCodecBufferAttr attr = {
536 ? AVCODEC_BUFFER_FLAGS_SYNC_FRAME : 0,
539 err = OH_AVBuffer_SetBufferAttr(input->
buffer, &attr);
540 if (err != AV_ERR_OK) {
544 err = OH_VideoEncoder_PushInputBuffer(
s->enc, input->
index);
545 if (err != AV_ERR_OK) {
566 while (!
s->encode_status) {
570 if (
s->eof_sent && !
s->encode_status)
576 ret =
s->encode_status;
585 if (!
s->frame->buf[0]) {
592 if (
s->native_window) {
601 while (!
s->encode_status) {
607 ret =
s->encode_status;
625 OH_VideoEncoder_Flush(
s->enc);
631 s->encode_status = 0;
636 OH_VideoEncoder_Start(
s->enc);
655#define OFFSET(x) offsetof(OHCodecEncContext, x)
656#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
658 {
"codec_name",
"Select codec by name",
660 {
"allow_sw",
"Allow software encoding",
662 {
"bitrate_mode",
"Bitrate control method",
664 {
"cbr",
"Constant bitrate mode",
666 {
"vbr",
"Variable bitrate mode",
668 {
"cq",
"Constant quality mode",
673#define DECLARE_OHCODEC_CLASS(name) \
674static const AVClass name ## _oh_enc_class = { \
675 .class_name = #name "_ohcodec", \
676 .item_name = av_default_item_name, \
677 .option = ohcodec_venc_options, \
678 .version = LIBAVUTIL_VERSION_INT, \
681#define DECLARE_OHCODEC_ENCODER(short_name, long_name, codec_id) \
682DECLARE_OHCODEC_CLASS(short_name) \
683const FFCodec ff_ ## short_name ## _oh_encoder = { \
684 .p.name = #short_name "_ohcodec", \
685 CODEC_LONG_NAME(long_name " OpenHarmony Codec"), \
686 .p.type = AVMEDIA_TYPE_VIDEO, \
688 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | \
689 AV_CODEC_CAP_HARDWARE | \
690 AV_CODEC_CAP_ENCODER_FLUSH, \
691 .priv_data_size = sizeof(OHCodecEncContext), \
692 CODEC_PIXFMTS_ARRAY(ohcodec_pix_fmts), \
693 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, \
694 .defaults = ohcodec_defaults, \
695 .init = oh_encode_init, \
696 FF_CODEC_RECEIVE_PACKET_CB(oh_encode_receive), \
697 .close = oh_encode_close, \
698 .flush = oh_encode_flush, \
699 .p.priv_class = &short_name ## _oh_enc_class, \
700 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \
701 .p.wrapper_name = "ohcodec", \
702 .hw_configs = oh_hw_configs, \
705#if CONFIG_H264_OH_ENCODER
709#if CONFIG_HEVC_OH_ENCODER
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static const char *const format[]
Libavcodec external API header.
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ 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...
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
@ AV_CODEC_HW_CONFIG_METHOD_AD_HOC
The codec supports this format by some ad-hoc method.
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, uint8_t *data, size_t size)
Wrap an existing array as a packet side data.
#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_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#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_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static AVRational av_make_q(int num, int den)
Create an AVRational.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
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_TIME_BASE_Q
Internal time base represented as fractional value.
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
@ AV_HWDEVICE_TYPE_OHCODEC
static int ff_cond_wait(AVCond *cond, AVMutex *mutex)
static int ff_mutex_unlock(AVMutex *mutex)
static int ff_cond_destroy(AVCond *cond)
static int ff_mutex_lock(AVMutex *mutex)
static int ff_mutex_destroy(AVMutex *mutex)
static int ff_cond_init(AVCond *cond, const void *attr)
static int ff_cond_signal(AVCond *cond)
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Memory handling functions.
int ff_oh_pix_from_ff_pix(enum AVPixelFormat pix)
int ff_oh_err_to_ff_err(OH_AVErrCode err)
static const char * ff_oh_mime(enum AVCodecID codec_id, void *log)
static const AVCodecHWConfigInternal *const oh_hw_configs[]
static enum AVPixelFormat ohcodec_pix_fmts[]
static int oh_encode_receive(AVCodecContext *avctx, AVPacket *pkt)
#define DECLARE_OHCODEC_ENCODER(short_name, long_name, codec_id)
static void oh_encode_on_output(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
static int oh_encode_output_packet(AVCodecContext *avctx, AVPacket *pkt, OHBufferQueueItem *output)
static int oh_encode_create(OHCodecEncContext *s, AVCodecContext *avctx)
static int oh_encode_start(OHCodecEncContext *s, AVCodecContext *avctx)
static void oh_encode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format, void *userdata)
static int oh_encode_send_hw_frame(AVCodecContext *avctx)
static int oh_encode_send_sw_frame(AVCodecContext *avctx, OHBufferQueueItem *input)
static void oh_encode_flush(AVCodecContext *avctx)
static const FFCodecDefault ohcodec_defaults[]
static int oh_encode_set_format(OHCodecEncContext *s, AVCodecContext *avctx)
static const AVOption ohcodec_venc_options[]
static void oh_encode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
static av_cold int oh_encode_close(AVCodecContext *avctx)
static void oh_encode_on_need_input(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
static av_cold int oh_encode_init(AVCodecContext *avctx)
AVPixelFormat
Pixel format.
@ 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...
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.
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
int64_t bit_rate
the average bitrate
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
int flags
AV_CODEC_FLAG_*.
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.
OpenHarmony codec device.
void * native_window
Pointer to OHNativeWindow.
This structure stores compressed data.
OHNativeWindow * native_window
static double cb(void *priv, double x, double y)