FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ohenc.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * Copyright (c) 2025 Zhao Zhili <quinkblack@foxmail.com>
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "config_components.h"
22 
23 #include <stdbool.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>
27 
28 #include "libavutil/fifo.h"
29 #include "libavutil/hwcontext_oh.h"
30 #include "libavutil/imgutils.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/thread.h"
34 
35 #include "avcodec.h"
36 #include "codec_internal.h"
37 #include "encode.h"
38 #include "hwconfig.h"
39 #include "ohcodec.h"
40 
41 typedef struct OHCodecEncContext {
43  OH_AVCodec *enc;
44 
48 
52 
54  uint8_t *extradata;
56 
58  bool eof_sent;
59 
61  int stride;
63 
64  OHNativeWindow *native_window;
65  char *name;
66  int allow_sw;
69 
70 static const enum AVPixelFormat ohcodec_pix_fmts[] = {
74 };
75 
77 {
78  const char *name = s->name;
79 
80  if (!name) {
81  const char *mime = ff_oh_mime(avctx->codec_id, avctx);
82  if (!mime)
83  return AVERROR_BUG;
84  OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(mime, true, HARDWARE);
85  if (!cap) {
86  if (!s->allow_sw) {
87  av_log(avctx, AV_LOG_ERROR, "Failed to get hardware codec %s\n", mime);
88  return AVERROR_EXTERNAL;
89  }
90  av_log(avctx, AV_LOG_WARNING,
91  "Failed to get hardware codec %s, try software backend\n", mime);
92  cap = OH_AVCodec_GetCapabilityByCategory(mime, true, SOFTWARE);
93  if (!cap) {
94  av_log(avctx, AV_LOG_ERROR, "Failed to get software codec %s\n", mime);
95  return AVERROR_EXTERNAL;
96  }
97  }
98  name = OH_AVCapability_GetName(cap);
99  if (!name)
100  return AVERROR_EXTERNAL;
101  }
102 
103  s->enc = OH_VideoEncoder_CreateByName(name);
104  if (!s->enc) {
105  av_log(avctx, AV_LOG_ERROR, "Create encoder with name %s failed\n", name);
106  return AVERROR_EXTERNAL;
107  }
108  av_log(avctx, AV_LOG_DEBUG, "Create encoder %s success\n", name);
109 
110  return 0;
111 }
112 
114 {
115  int ret;
116 
117  OH_AVFormat *format = OH_AVFormat_Create();
118  if (!format)
119  return AVERROR(ENOMEM);
120 
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);
123  if (!b) {
124  av_log(avctx, AV_LOG_ERROR, "Set width/height (%dx%d) failed\n",
125  avctx->width, avctx->height);
127  goto out;
128  }
129  if (avctx->framerate.num && avctx->framerate.den)
130  OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE,
131  av_q2d(avctx->framerate));
132  int pix = ff_oh_pix_from_ff_pix(avctx->pix_fmt);
133  if (!pix) {
134  ret = AVERROR_BUG;
135  goto out;
136  }
137  b = OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, pix);
138  if (!b) {
139  av_log(avctx, AV_LOG_ERROR, "Set pixel format to %d failed\n", pix);
141  goto out;
142  }
143 
144  if (s->bitrate_mode != -1) {
145  b = OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, s->bitrate_mode);
146  if (!b) {
147  av_log(avctx, AV_LOG_ERROR, "Set bitrate mode to %d failed\n",
148  s->bitrate_mode);
150  goto out;
151  }
152  }
153  OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, avctx->bit_rate);
154 
155  if (avctx->gop_size > 0) {
156  if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
157  // In milliseconds
158  int gop = av_rescale_q(avctx->gop_size,
159  av_make_q(avctx->framerate.den,
160  avctx->framerate.num),
161  av_make_q(1, 1000));
162  OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, gop);
163  } else {
164  av_log(avctx, AV_LOG_WARNING, "Skip setting gop without framerate\n");
165  }
166  } else if (!avctx->gop_size) {
167  // All frames are key frame
168  OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, 0);
169  } else if (avctx->gop_size == -1) {
170  // Infinite gop
171  OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, -1);
172  }
173 
174  OH_AVErrCode err = OH_VideoEncoder_Configure(s->enc, format);
175  if (err != AV_ERR_OK) {
176  ret = ff_oh_err_to_ff_err(err);
177  av_log(avctx, AV_LOG_ERROR, "Decoder configure failed, %d, %s\n",
178  err, av_err2str(ret));
179  goto out;
180  }
181 
182  if (avctx->pix_fmt == AV_PIX_FMT_OHCODEC) {
183  if (avctx->hw_device_ctx) {
184  av_log(avctx, AV_LOG_ERROR,
185  "ohcodec can only export native window via hw device, "
186  "doesn't support import hw device\n");
187  ret = AVERROR(EINVAL);
188  goto out;
189  }
190 
191  err = OH_VideoEncoder_GetSurface(s->enc, &s->native_window);
192  if (err != AV_ERR_OK) {
193  ret = ff_oh_err_to_ff_err(err);
194  av_log(avctx, AV_LOG_ERROR, "Get surface failed, %d, %s\n",
195  err, av_err2str(ret));
196  goto out;
197  }
198  av_log(avctx, AV_LOG_INFO, "Native window %p\n", s->native_window);
199 
202  if (ret < 0)
203  goto out;
204 
205  AVOHCodecDeviceContext *dev = ((AVHWDeviceContext *)avctx->hw_device_ctx->data)->hwctx;
206  dev->native_window = s->native_window;
207  }
208 
209  return 0;
210 out:
211  OH_AVFormat_Destroy(format);
212  return ret;
213 }
214 
215 static void oh_encode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
216 {
217  AVCodecContext *avctx = userdata;
218  OHCodecEncContext *s = avctx->priv_data;
219 
220  // Careful on the lock order.
221  // Always lock input first.
222  ff_mutex_lock(&s->input_mutex);
223  ff_mutex_lock(&s->output_mutex);
224  s->encode_status = ff_oh_err_to_ff_err(err);
225  ff_mutex_unlock(&s->output_mutex);
226  ff_mutex_unlock(&s->input_mutex);
227 
228  ff_cond_signal(&s->output_cond);
229  ff_cond_signal(&s->input_cond);
230 }
231 
232 static void oh_encode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format,
233  void *userdata)
234 {
235  AVCodecContext *avctx = userdata;
236  OHCodecEncContext *s = avctx->priv_data;
237 
238  if (!OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &s->stride))
239  s->stride = avctx->width;
240  if (!OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &s->slice_height))
241  s->slice_height = avctx->height;
242 
243  s->got_stream_info = true;
244 }
245 
246 static void oh_encode_on_need_input(OH_AVCodec *codec, uint32_t index,
247  OH_AVBuffer *buffer, void *userdata)
248 {
249  AVCodecContext *avctx = userdata;
250  OHCodecEncContext *s = avctx->priv_data;
251  OHBufferQueueItem item = {
252  index, buffer,
253  };
254 
255  ff_mutex_lock(&s->input_mutex);
256  int ret = av_fifo_write(s->input_queue, &item, 1);
257  if (ret >= 0)
258  ff_cond_signal(&s->input_cond);
259  ff_mutex_unlock(&s->input_mutex);
260 
261  if (ret < 0)
262  oh_encode_on_err(codec, AV_ERR_NO_MEMORY, userdata);
263 }
264 
265 static void oh_encode_on_output(OH_AVCodec *codec, uint32_t index,
266  OH_AVBuffer *buffer, void *userdata)
267 {
268  AVCodecContext *avctx = userdata;
269  OHCodecEncContext *s = avctx->priv_data;
270  OHBufferQueueItem item = {
271  index, buffer,
272  };
273 
274  ff_mutex_lock(&s->output_mutex);
275  int ret = av_fifo_write(s->output_queue, &item, 1);
276  if (ret >= 0)
277  ff_cond_signal(&s->output_cond);
278  ff_mutex_unlock(&s->output_mutex);
279 
280  if (ret < 0)
281  oh_encode_on_err(codec, AV_ERR_NO_MEMORY, userdata);
282 }
283 
285 {
286  int ret;
287  OH_AVErrCode err;
288  OH_AVCodecCallback cb = {
289  .onError = oh_encode_on_err,
290  .onStreamChanged = oh_encode_on_stream_changed,
291  .onNeedInputBuffer = oh_encode_on_need_input,
292  .onNewOutputBuffer = oh_encode_on_output,
293  };
294 
295  err = OH_VideoEncoder_RegisterCallback(s->enc, cb, avctx);
296  if (err != AV_ERR_OK) {
297  ret = ff_oh_err_to_ff_err(err);
298  av_log(avctx, AV_LOG_ERROR, "Register callback failed, %d, %s\n",
299  err, av_err2str(ret));
300  return ret;
301  }
302  err = OH_VideoEncoder_Prepare(s->enc);
303  if (err != AV_ERR_OK) {
304  ret = ff_oh_err_to_ff_err(err);
305  av_log(avctx, AV_LOG_ERROR, "Prepare failed, %d, %s\n",
306  err, av_err2str(ret));
307  return ret;
308  }
309  err = OH_VideoEncoder_Start(s->enc);
310  if (err != AV_ERR_OK) {
311  ret = ff_oh_err_to_ff_err(err);
312  av_log(avctx, AV_LOG_ERROR, "Start failed, %d, %s\n",
313  err, av_err2str(ret));
314  return ret;
315  }
316 
317  return 0;
318 }
319 
321 {
322  OHCodecEncContext *s = avctx->priv_data;
323 
324  // Initialize these fields first, so oh_decode_close can destroy them safely
325  ff_mutex_init(&s->input_mutex, NULL);
326  ff_cond_init(&s->input_cond, NULL);
327  ff_mutex_init(&s->output_mutex, NULL);
328  ff_cond_init(&s->output_cond, NULL);
329 
330  int ret = oh_encode_create(s, avctx);
331  if (ret < 0)
332  return ret;
333  ret = oh_encode_set_format(s, avctx);
334  if (ret < 0)
335  return ret;
336 
337  size_t fifo_size = 16;
338  s->input_queue = av_fifo_alloc2(fifo_size, sizeof(OHBufferQueueItem),
340  s->output_queue = av_fifo_alloc2(fifo_size, sizeof(OHBufferQueueItem),
342  s->frame = av_frame_alloc();
343  if (!s->input_queue || !s->output_queue || !s->frame)
344  return AVERROR(ENOMEM);
345 
346  ret = oh_encode_start(s, avctx);
347  if (ret < 0)
348  return ret;
349 
350  return 0;
351 }
352 
354 {
355  OHCodecEncContext *s = avctx->priv_data;
356 
357  if (s->enc) {
358  if (s->native_window) {
359  OH_NativeWindow_DestroyNativeWindow(s->native_window);
360  s->native_window = NULL;
361  }
362  OH_VideoEncoder_Stop(s->enc);
363  OH_AVErrCode err = OH_VideoEncoder_Destroy(s->enc);
364  if (err == AV_ERR_OK)
365  av_log(avctx, AV_LOG_DEBUG, "Destroy encoder success\n");
366  else
367  av_log(avctx, AV_LOG_ERROR, "Destroy decoder failed, %d, %s\n",
368  err, av_err2str(ff_oh_err_to_ff_err(err)));
369  s->enc = NULL;
370  }
371 
372  av_freep(&s->extradata);
373  av_frame_free(&s->frame);
374 
375  ff_mutex_destroy(&s->input_mutex);
376  ff_cond_destroy(&s->input_cond);
377  av_fifo_freep2(&s->input_queue);
378 
379  ff_mutex_destroy(&s->output_mutex);
380  ff_cond_destroy(&s->output_cond);
381  av_fifo_freep2(&s->output_queue);
382 
383  return 0;
384 }
385 
388 {
389  OHCodecEncContext *s = avctx->priv_data;
390  uint8_t *p;
391  OH_AVCodecBufferAttr attr;
392  int ret;
393 
394  OH_AVErrCode err = OH_AVBuffer_GetBufferAttr(output->buffer, &attr);
395  if (err != AV_ERR_OK) {
396  ret = ff_oh_err_to_ff_err(err);
397  goto out;
398  }
399  if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
400  av_log(avctx, AV_LOG_DEBUG, "Buffer flag eos\n");
401  ret = AVERROR_EOF;
402  goto out;
403  }
404 
405  p = OH_AVBuffer_GetAddr(output->buffer);
406  if (!p) {
407  av_log(avctx, AV_LOG_ERROR, "Failed to get output buffer addr\n");
409  goto out;
410  }
411  if (attr.flags & AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
412  av_freep(&s->extradata);
413  s->extradata = av_malloc(attr.size + AV_INPUT_BUFFER_PADDING_SIZE);
414  if (!s->extradata) {
415  ret = AVERROR(ENOMEM);
416  goto out;
417  }
418  memset(s->extradata + attr.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
419  memcpy(s->extradata, p + attr.offset, attr.size);
420  s->extradata_size = attr.size;
421  ret = 0;
422  goto out;
423  }
424 
425  int64_t extradata_size = s->extradata_size;
426  s->extradata_size = 0;
427 
428  if (extradata_size && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
430  s->extradata, extradata_size);
431  if (ret < 0)
432  goto out;
433  s->extradata = NULL;
434  extradata_size = 0;
435  }
436 
437  ret = ff_get_encode_buffer(avctx, pkt, attr.size + extradata_size, 0);
438  if (ret < 0)
439  goto out;
440 
441  if (extradata_size)
442  memcpy(pkt->data, s->extradata, extradata_size);
443 
444  memcpy(pkt->data + extradata_size, p + attr.offset, attr.size);
445  pkt->pts = av_rescale_q(attr.pts, AV_TIME_BASE_Q, avctx->time_base);
446  if (attr.flags & AVCODEC_BUFFER_FLAGS_SYNC_FRAME)
448  ret = 0;
449 out:
450  OH_VideoEncoder_FreeOutputBuffer(s->enc, output->index);
451  return ret;
452 }
453 
455 {
456  OHCodecEncContext *s = avctx->priv_data;
457 
458  if (s->eof_sent)
459  return 0;
460 
461  if (s->frame->buf[0]) {
462  av_frame_unref(s->frame);
463  return 0;
464  }
465 
466  OH_AVErrCode err = OH_VideoEncoder_NotifyEndOfStream(s->enc);
467  s->eof_sent = true;
468  return ff_oh_err_to_ff_err(err);
469 }
470 
472 {
473  OHCodecEncContext *s = avctx->priv_data;
474  AVFrame *frame = s->frame;
475  OH_AVErrCode err;
476  int ret;
477 
478  if (!s->got_stream_info) {
479  // This shouldn't happen, add a warning message.
480  av_log(avctx, AV_LOG_WARNING,
481  "decoder didn't notify stream info, try get format explicitly\n");
482 
483  OH_AVFormat *format = OH_VideoEncoder_GetOutputDescription(s->enc);
484  if (!format) {
485  av_log(avctx, AV_LOG_ERROR, "GetOutputDescription failed\n");
486  return AVERROR_EXTERNAL;
487  }
488 
489  oh_encode_on_stream_changed(s->enc, format, avctx);
490  OH_AVFormat_Destroy(format);
491  if (!s->got_stream_info)
492  return AVERROR_EXTERNAL;
493  }
494 
495  if (!frame->buf[0] && !s->eof_sent) {
496  OH_AVCodecBufferAttr attr = {
497  .flags = AVCODEC_BUFFER_FLAGS_EOS,
498  };
499  err = OH_AVBuffer_SetBufferAttr(input->buffer, &attr);
500  if (err != AV_ERR_OK)
501  return ff_oh_err_to_ff_err(err);
502  err = OH_VideoEncoder_PushInputBuffer(s->enc, input->index);
503  if (err != AV_ERR_OK)
504  return ff_oh_err_to_ff_err(err);
505  s->eof_sent = true;
506  return 0;
507  }
508 
509  uint8_t *p = OH_AVBuffer_GetAddr(input->buffer);
510  int32_t n = OH_AVBuffer_GetCapacity(input->buffer);
511  if (!p || n <= 0) {
512  av_log(avctx, AV_LOG_ERROR,
513  "Failed to get buffer addr (%p) or capacity (%d)\n",
514  p, n);
515  return AVERROR_EXTERNAL;
516  }
517 
518  uint8_t *dst[4] = {0};
519  int dst_linesizes[4] = {0};
520  ret = av_image_fill_linesizes(dst_linesizes, frame->format, s->stride);
521  if (ret < 0)
522  return ret;
523  ret = av_image_fill_pointers(dst, frame->format, s->slice_height, p,
524  dst_linesizes);
525  if (ret < 0)
526  return ret;
527 
528  av_image_copy2(dst, dst_linesizes, frame->data, frame->linesize,
529  frame->format, frame->width, frame->height);
530  OH_AVCodecBufferAttr attr = {
531  .size = n,
532  .offset = 0,
533  .pts = av_rescale_q(s->frame->pts, avctx->pkt_timebase,
535  .flags = (s->frame->flags & AV_FRAME_FLAG_KEY)
536  ? AVCODEC_BUFFER_FLAGS_SYNC_FRAME : 0,
537  };
538 
539  err = OH_AVBuffer_SetBufferAttr(input->buffer, &attr);
540  if (err != AV_ERR_OK) {
541  ret = ff_oh_err_to_ff_err(err);
542  return ret;
543  }
544  err = OH_VideoEncoder_PushInputBuffer(s->enc, input->index);
545  if (err != AV_ERR_OK) {
546  ret = ff_oh_err_to_ff_err(err);
547  av_log(avctx, AV_LOG_ERROR, "Push input buffer failed, %d, %s\n",
548  err, av_err2str(ret));
549  return ret;
550  }
551  av_frame_unref(s->frame);
552 
553  return 0;
554 }
555 
557 {
558  OHCodecEncContext *s = avctx->priv_data;
559 
560  while (1) {
562  int ret;
563 
564  // Try get output
565  ff_mutex_lock(&s->output_mutex);
566  while (!s->encode_status) {
567  if (av_fifo_read(s->output_queue, &buffer, 1) >= 0)
568  break;
569  // Only wait after send EOF
570  if (s->eof_sent && !s->encode_status)
571  ff_cond_wait(&s->output_cond, &s->output_mutex);
572  else
573  break;
574  }
575 
576  ret = s->encode_status;
577  ff_mutex_unlock(&s->output_mutex);
578 
579  // Got a packet
580  if (buffer.buffer)
581  return oh_encode_output_packet(avctx, pkt, &buffer);
582  if (ret < 0)
583  return ret;
584 
585  if (!s->frame->buf[0]) {
586  /* fetch new frame or eof */
587  ret = ff_encode_get_frame(avctx, s->frame);
588  if (ret < 0 && ret != AVERROR_EOF)
589  return ret;
590  }
591 
592  if (s->native_window) {
593  ret = oh_encode_send_hw_frame(avctx);
594  if (ret < 0)
595  return ret;
596  continue;
597  }
598 
599  // Wait input buffer
600  ff_mutex_lock(&s->input_mutex);
601  while (!s->encode_status) {
602  if (av_fifo_read(s->input_queue, &buffer, 1) >= 0)
603  break;
604  ff_cond_wait(&s->input_cond, &s->input_mutex);
605  }
606 
607  ret = s->encode_status;
608  ff_mutex_unlock(&s->input_mutex);
609 
610  if (ret < 0)
611  return ret;
612 
614  if (ret < 0)
615  return ret;
616  }
617 
618  return AVERROR(EAGAIN);
619 }
620 
621 static void oh_encode_flush(AVCodecContext *avctx)
622 {
623  OHCodecEncContext *s = avctx->priv_data;
624 
625  OH_VideoEncoder_Flush(s->enc);
626 
627  ff_mutex_lock(&s->input_mutex);
628  ff_mutex_lock(&s->output_mutex);
629  av_fifo_reset2(s->input_queue);
630  av_fifo_reset2(s->output_queue);
631  s->encode_status = 0;
632  s->eof_sent = false;
633  ff_mutex_unlock(&s->output_mutex);
634  ff_mutex_unlock(&s->input_mutex);
635 
636  OH_VideoEncoder_Start(s->enc);
637 }
638 
639 static const AVCodecHWConfigInternal *const oh_hw_configs[] = {
640  &(const AVCodecHWConfigInternal) {
641  .public = {
644  },
645  .hwaccel = NULL,
646  },
647  NULL
648 };
649 
651  {"g", "-2"},
652  {NULL},
653 };
654 
655 #define OFFSET(x) offsetof(OHCodecEncContext, x)
656 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
657 static const AVOption ohcodec_venc_options[] = {
658  {"codec_name", "Select codec by name",
659  OFFSET(name), AV_OPT_TYPE_STRING, .flags = VE},
660  {"allow_sw", "Allow software encoding",
661  OFFSET(allow_sw), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE},
662  {"bitrate_mode", "Bitrate control method",
663  OFFSET(bitrate_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, .unit = "bitrate_mode"},
664  {"cbr", "Constant bitrate mode",
665  0, AV_OPT_TYPE_CONST, {.i64 = CBR}, 0, 0, VE, .unit = "bitrate_mode"},
666  {"vbr", "Variable bitrate mode",
667  0, AV_OPT_TYPE_CONST, {.i64 = VBR}, 0, 0, VE, .unit = "bitrate_mode"},
668  {"cq", "Constant quality mode",
669  0, AV_OPT_TYPE_CONST, {.i64 = CQ}, 0, 0, VE, .unit = "bitrate_mode"},
670  {NULL},
671 };
672 
673 #define DECLARE_OHCODEC_CLASS(name) \
674 static 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, \
679 }; \
680 
681 #define DECLARE_OHCODEC_ENCODER(short_name, long_name, codec_id) \
682 DECLARE_OHCODEC_CLASS(short_name) \
683 const 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, \
687  .p.id = codec_id, \
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, \
703 }; \
704 
705 #if CONFIG_H264_OH_ENCODER
707 #endif // CONFIG_H264_OH_ENCODER
708 
709 #if CONFIG_HEVC_OH_ENCODER
711 #endif // CONFIG_HEVC_OH_ENCODER
712 
hwconfig.h
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
oh_encode_send_hw_frame
static int oh_encode_send_hw_frame(AVCodecContext *avctx)
Definition: ohenc.c:454
ff_mutex_init
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition: thread.h:187
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
out
FILE * out
Definition: movenc.c:55
oh_encode_output_packet
static int oh_encode_output_packet(AVCodecContext *avctx, AVPacket *pkt, OHBufferQueueItem *output)
Definition: ohenc.c:386
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:247
OHBufferQueueItem
Definition: ohcodec.h:33
OHCodecEncContext::output_mutex
AVMutex output_mutex
Definition: ohenc.c:49
thread.h
AV_PKT_DATA_NEW_EXTRADATA
@ 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...
Definition: packet.h:56
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
oh_encode_create
static int oh_encode_create(OHCodecEncContext *s, AVCodecContext *avctx)
Definition: ohenc.c:76
OHCodecEncContext::eof_sent
bool eof_sent
Definition: ohenc.c:58
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:263
int64_t
long long int64_t
Definition: coverity.c:34
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:226
OHCodecEncContext::extradata_size
int extradata_size
Definition: ohenc.c:55
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:63
ohcodec_venc_options
static const AVOption ohcodec_venc_options[]
Definition: ohenc.c:657
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:421
AVPacket::data
uint8_t * data
Definition: packet.h:552
AVOption
AVOption.
Definition: opt.h:429
encode.h
b
#define b
Definition: input.c:42
pix
enum AVPixelFormat pix
Definition: ohcodec.c:55
oh_encode_on_stream_changed
static void oh_encode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format, void *userdata)
Definition: ohenc.c:232
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:607
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
AV_CODEC_FLAG_GLOBAL_HEADER
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:318
ff_mutex_unlock
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:189
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:551
fifo.h
FFCodecDefault
Definition: codec_internal.h:96
VE
#define VE
Definition: ohenc.c:656
av_packet_add_side_data
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.
Definition: packet.c:198
av_fifo_write
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition: fifo.c:188
OHCodecEncContext::input_queue
AVFifo * input_queue
Definition: ohenc.c:47
oh_encode_send_sw_frame
static int oh_encode_send_sw_frame(AVCodecContext *avctx, OHBufferQueueItem *input)
Definition: ohenc.c:471
AV_CODEC_HW_CONFIG_METHOD_AD_HOC
@ AV_CODEC_HW_CONFIG_METHOD_AD_HOC
The codec supports this format by some ad-hoc method.
Definition: codec.h:327
ohcodec.h
oh_encode_close
static av_cold int oh_encode_close(AVCodecContext *avctx)
Definition: ohenc.c:353
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:488
av_image_fill_pointers
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.
Definition: imgutils.c:145
AVRational::num
int num
Numerator.
Definition: rational.h:59
ff_oh_err_to_ff_err
int ff_oh_err_to_ff_err(OH_AVErrCode err)
Definition: ohcodec.c:25
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:51
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
OHCodecEncContext::extradata
uint8_t * extradata
Definition: ohenc.c:54
av_cold
#define av_cold
Definition: attributes.h:90
av_fifo_read
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition: fifo.c:240
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:636
oh_encode_start
static int oh_encode_start(OHCodecEncContext *s, AVCodecContext *avctx)
Definition: ohenc.c:284
AVMutex
#define AVMutex
Definition: thread.h:184
ohcodec_defaults
static const FFCodecDefault ohcodec_defaults[]
Definition: ohenc.c:650
av_image_fill_linesizes
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.
Definition: imgutils.c:89
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
hwcontext_oh.h
ff_cond_wait
static int ff_cond_wait(AVCond *cond, AVMutex *mutex)
Definition: thread.h:198
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
OHCodecEncContext::bitrate_mode
int bitrate_mode
Definition: ohenc.c:67
AVCond
#define AVCond
Definition: thread.h:192
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVCodecHWConfig::pix_fmt
enum AVPixelFormat pix_fmt
For decoders, a hardware pixel format which that decoder may be able to decode to if suitable hardwar...
Definition: codec.h:339
OHCodecEncContext::output_queue
AVFifo * output_queue
Definition: ohenc.c:51
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:441
OHCodecEncContext::output_cond
AVCond output_cond
Definition: ohenc.c:50
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
oh_encode_on_need_input
static void oh_encode_on_need_input(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
Definition: ohenc.c:246
NULL
#define NULL
Definition: coverity.c:32
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:481
oh_encode_on_err
static void oh_encode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
Definition: ohenc.c:215
index
int index
Definition: gxfenc.c:90
OHCodecEncContext::input_cond
AVCond input_cond
Definition: ohenc.c:46
AV_HWDEVICE_TYPE_OHCODEC
@ AV_HWDEVICE_TYPE_OHCODEC
Definition: hwcontext.h:43
ff_mutex_destroy
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:190
OHCodecEncContext::got_stream_info
bool got_stream_info
Definition: ohenc.c:60
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avcodec.h:535
av_fifo_reset2
void av_fifo_reset2(AVFifo *f)
Definition: fifo.c:280
ff_oh_mime
static const char * ff_oh_mime(enum AVCodecID codec_id, void *log)
Definition: ohcodec.h:40
OHCodecEncContext::enc
OH_AVCodec * enc
Definition: ohenc.c:43
OHCodecEncContext
Definition: ohenc.c:41
oh_encode_receive
static int oh_encode_receive(AVCodecContext *avctx, AVPacket *pkt)
Definition: ohenc.c:556
AVPacket::size
int size
Definition: packet.h:553
AVFifo
Definition: fifo.c:35
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1005
codec_internal.h
OHCodecEncContext::allow_sw
int allow_sw
Definition: ohenc.c:66
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
oh_encode_on_output
static void oh_encode_on_output(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
Definition: ohenc.c:265
AVCodecContext::pkt_timebase
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition: avcodec.h:542
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
OHCodecEncContext::encode_status
int encode_status
Definition: ohenc.c:57
AVCodecHWConfigInternal
Definition: hwconfig.h:25
OHCodecEncContext::input_mutex
AVMutex input_mutex
Definition: ohenc.c:45
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
ff_mutex_lock
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:188
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:558
OHCodecEncContext::native_window
OHNativeWindow * native_window
Definition: ohenc.c:64
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:545
oh_encode_init
static av_cold int oh_encode_init(AVCodecContext *avctx)
Definition: ohenc.c:320
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:494
AVCodecContext::hw_device_ctx
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition: avcodec.h:1475
OHCodecEncContext::avclass
AVClass * avclass
Definition: ohenc.c:42
CBR
@ CBR
Definition: af_afade.c:60
AVCodecContext::height
int height
Definition: avcodec.h:592
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:631
OHCodecEncContext::frame
AVFrame * frame
Definition: ohenc.c:53
oh_encode_flush
static void oh_encode_flush(AVCodecContext *avctx)
Definition: ohenc.c:621
avcodec.h
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ 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...
Definition: pixfmt.h:96
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
oh_encode_set_format
static int oh_encode_set_format(OHCodecEncContext *s, AVCodecContext *avctx)
Definition: ohenc.c:113
av_hwdevice_ctx_create
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.
Definition: hwcontext.c:615
av_fifo_alloc2
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.
Definition: fifo.c:47
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
oh_hw_configs
static const AVCodecHWConfigInternal *const oh_hw_configs[]
Definition: ohenc.c:639
OHCodecEncContext::stride
int stride
Definition: ohenc.c:61
AVCodecContext
main external API structure.
Definition: avcodec.h:431
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_get_encode_buffer
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition: encode.c:106
DECLARE_OHCODEC_ENCODER
#define DECLARE_OHCODEC_ENCODER(short_name, long_name, codec_id)
Definition: ohenc.c:681
av_image_copy2
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 ...
Definition: imgutils.h:184
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
AVOHCodecDeviceContext
OpenHarmony codec device.
Definition: hwcontext_oh.h:27
ff_cond_signal
static int ff_cond_signal(AVCond *cond)
Definition: thread.h:196
mem.h
ff_encode_get_frame
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
Definition: encode.c:205
AV_PIX_FMT_OHCODEC
@ AV_PIX_FMT_OHCODEC
Definition: pixfmt.h:500
ff_cond_destroy
static int ff_cond_destroy(AVCond *cond)
Definition: thread.h:195
AVPacket
This structure stores compressed data.
Definition: packet.h:529
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
ohcodec_pix_fmts
static enum AVPixelFormat ohcodec_pix_fmts[]
Definition: ohenc.c:70
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:592
int32_t
int32_t
Definition: audioconvert.c:56
imgutils.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
ff_cond_init
static int ff_cond_init(AVCond *cond, const void *attr)
Definition: thread.h:194
AVOHCodecDeviceContext::native_window
void * native_window
Pointer to OHNativeWindow.
Definition: hwcontext_oh.h:31
AV_OPT_TYPE_STRING
@ 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...
Definition: opt.h:276
AVCodecHWConfigInternal::public
AVCodecHWConfig public
This is the structure which will be returned to the user by avcodec_get_hw_config().
Definition: hwconfig.h:30
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
OHCodecEncContext::name
char * name
Definition: ohenc.c:65
OHCodecEncContext::slice_height
int slice_height
Definition: ohenc.c:62
fifo_size
size_t fifo_size
Definition: dts2pts.c:371
AV_FIFO_FLAG_AUTO_GROW
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition: fifo.h:63
OFFSET
#define OFFSET(x)
Definition: ohenc.c:655
ff_oh_pix_from_ff_pix
int ff_oh_pix_from_ff_pix(enum AVPixelFormat pix)
Definition: ohcodec.c:72