FFmpeg
Loading...
Searching...
No Matches
ohdec.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_videodecoder.h>
26
27#include "libavutil/fifo.h"
29#include "libavutil/imgutils.h"
30#include "libavutil/mem.h"
31#include "libavutil/opt.h"
32#include "libavutil/refstruct.h"
33#include "libavutil/thread.h"
34
35#include "avcodec.h"
36#include "codec_internal.h"
37#include "decode.h"
38#include "hwconfig.h"
39#include "ohcodec.h"
40#include "pthread_internal.h"
41
42typedef struct OHCodecDecContext {
44 OH_AVCodec *dec;
45 /* A RefStruct reference backing dec. Each hardware frame has a reference count to
46 * dec. dec will be destroyed only after oh_decode_close and all hardware
47 * frames have been released.
48 */
49 OH_AVCodec **dec_ref;
50
54
58
60
63
66 int width;
67 int height;
68 int stride;
70 OH_AVPixelFormat pix_fmt;
71
72 char *name;
76
77#define OFFSET(x) offsetof(OHCodecDecContext, x)
78DEFINE_OFFSET_ARRAY(OHCodecDecContext, mutex_cond, mutex_cond_cnt,
79 (OFFSET(input_mutex), OFFSET(output_mutex)),
80 (OFFSET(input_cond), OFFSET(output_cond)));
81
82typedef struct OHCodecBuffer {
83 uint32_t index;
84 OH_AVBuffer *buffer;
85 OH_AVCodec **dec_ref; ///< RefStruct reference
87
88static void oh_decode_release(AVRefStructOpaque unused, void *obj)
89{
90 OH_AVCodec **decp = obj;
91 OH_AVErrCode err = OH_VideoDecoder_Destroy(*decp);
92 if (err == AV_ERR_OK)
93 av_log(NULL, AV_LOG_DEBUG, "Destroy decoder success\n");
94 else
95 av_log(NULL, AV_LOG_ERROR, "Destroy decoder failed, %d, %s\n",
97}
98
100{
101 const char *name = s->name;
102
103 if (!name) {
104 const char *mime = ff_oh_mime(avctx->codec_id, avctx);
105 if (!mime)
106 return AVERROR_BUG;
107 OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(mime, false, HARDWARE);
108 if (!cap) {
109 if (!s->allow_sw) {
110 av_log(avctx, AV_LOG_ERROR, "Failed to get hardware codec %s\n", mime);
111 return AVERROR_EXTERNAL;
112 }
113 av_log(avctx, AV_LOG_WARNING,
114 "Failed to get hardware codec %s, try software backend\n", mime);
115 cap = OH_AVCodec_GetCapabilityByCategory(mime, false, SOFTWARE);
116 if (!cap) {
117 av_log(avctx, AV_LOG_ERROR, "Failed to get software codec %s\n", mime);
118 return AVERROR_EXTERNAL;
119 }
120 }
121 name = OH_AVCapability_GetName(cap);
122 if (!name)
123 return AVERROR_EXTERNAL;
124 }
125
126 s->dec = OH_VideoDecoder_CreateByName(name);
127 if (!s->dec) {
128 av_log(avctx, AV_LOG_ERROR, "Create decoder with name %s failed\n", name);
129 return AVERROR_EXTERNAL;
130 }
131 av_log(avctx, AV_LOG_DEBUG, "Create decoder %s success\n", name);
132
133 s->dec_ref = av_refstruct_alloc_ext(sizeof(*s->dec_ref), 0, NULL, oh_decode_release);
134 if (!s->dec_ref) {
135 oh_decode_release((AVRefStructOpaque){.nc = NULL }, &s->dec);
136 s->dec = NULL;
137 return AVERROR(ENOMEM);
138 }
139 *s->dec_ref = s->dec;
140
141 return 0;
142}
143
145{
146 int ret;
147 OHNativeWindow *window = NULL;
148
149 if (avctx->hw_device_ctx) {
150 AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
151 if (device_ctx->type == AV_HWDEVICE_TYPE_OHCODEC) {
152 AVOHCodecDeviceContext *dev = device_ctx->hwctx;
153 window = dev->native_window;
154 s->output_to_window = true;
155 } else {
156 av_log(avctx, AV_LOG_WARNING, "Ignore invalid hw device type %s\n",
157 av_hwdevice_get_type_name(device_ctx->type));
158 }
159 }
160
161 if (avctx->width <= 0 || avctx->height <= 0) {
162 av_log(avctx, AV_LOG_ERROR,
163 "Invalid width/height (%dx%d), width and height are mandatory for ohcodec\n",
164 avctx->width, avctx->height);
165 return AVERROR(EINVAL);
166 }
167
168 OH_AVFormat *format = OH_AVFormat_Create();
169 if (!format)
170 return AVERROR(ENOMEM);
171
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);
177 else
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) {
183 ret = ff_oh_err_to_ff_err(err);
184 av_log(avctx, AV_LOG_ERROR, "Decoder configure failed, %d, %s\n",
185 err, av_err2str(ret));
186 return ret;
187 }
188
189 if (s->output_to_window) {
190 err = OH_VideoDecoder_SetSurface(s->dec, window);
191 if (err != AV_ERR_OK) {
192 ret = ff_oh_err_to_ff_err(err);
193 av_log(avctx, AV_LOG_ERROR, "Set surface failed, %d, %s\n",
194 err, av_err2str(ret));
195 return ret;
196 }
197 }
198
199 return 0;
200}
201
202static void oh_decode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
203{
204 AVCodecContext *avctx = userdata;
205 OHCodecDecContext *s = avctx->priv_data;
206
207 // Careful on the lock order.
208 // Always lock input first.
209 ff_mutex_lock(&s->input_mutex);
210 ff_mutex_lock(&s->output_mutex);
211 s->decode_status = ff_oh_err_to_ff_err(err);
212 ff_mutex_unlock(&s->output_mutex);
213 ff_mutex_unlock(&s->input_mutex);
214
215 ff_cond_signal(&s->output_cond);
216 ff_cond_signal(&s->input_cond);
217}
218
219static void oh_decode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format,
220 void *userdata)
221{
222 AVCodecContext *avctx = userdata;
223 OHCodecDecContext *s = avctx->priv_data;
224 int32_t n;
225 double d;
226
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,
231 &s->slice_height)) {
232 av_log(avctx, AV_LOG_ERROR, "Get dimension info from format failed\n");
233 goto out;
234 }
235
236 if (ff_set_dimensions(avctx, s->width, s->height) < 0)
237 goto out;
238
239 if (s->stride <= 0 || s->slice_height <= 0) {
240 av_log(avctx, AV_LOG_ERROR,
241 "Buffer stride (%d) or slice height (%d) is invalid\n",
242 s->stride, s->slice_height);
243 goto out;
244 }
245
246 if (OH_AVFormat_GetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, &n)) {
247 s->pix_fmt = n;
248 /* When use output_to_window, the returned format is the memory
249 * layout of hardware frame, not AV_PIXEL_FORMAT_SURFACE_FORMAT as
250 * expected.
251 */
252 if (s->output_to_window)
254 else
255 avctx->pix_fmt = ff_oh_pix_to_ff_pix(s->pix_fmt);
256 // Check whether this pixel format is supported
257 if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
258 av_log(avctx, AV_LOG_ERROR, "Unsupported OH_AVPixelFormat %d\n",
259 n);
260 goto out;
261 }
262 } else {
263 av_log(avctx, AV_LOG_ERROR, "Failed to get pixel format\n");
264 goto out;
265 }
266
267 if (OH_AVFormat_GetIntValue(format,
268 OH_MD_KEY_MATRIX_COEFFICIENTS,
269 &n))
270 avctx->colorspace = n;
271 if (OH_AVFormat_GetIntValue(format,
272 OH_MD_KEY_COLOR_PRIMARIES,
273 &n))
274 avctx->color_primaries = n;
275 if (OH_AVFormat_GetIntValue(format,
276 OH_MD_KEY_TRANSFER_CHARACTERISTICS,
277 &n))
278 avctx->color_trc = n;
279 if (OH_AVFormat_GetIntValue(format,
280 OH_MD_KEY_RANGE_FLAG,
281 &n))
283
284 if (OH_AVFormat_GetDoubleValue(format, OH_MD_KEY_VIDEO_SAR, &d)) {
285 AVRational sar = av_d2q(d, 4096 * 4);
286 ff_set_sar(avctx, sar);
287 }
288
289 s->got_stream_info = true;
290
291 return;
292out:
293 av_log(avctx, AV_LOG_ERROR, "Invalid format from decoder: %s\n",
294 OH_AVFormat_DumpInfo(format));
295 oh_decode_on_err(codec, AV_ERR_UNKNOWN, userdata);
296}
297
298static void oh_decode_on_need_input(OH_AVCodec *codec, uint32_t index,
299 OH_AVBuffer *buffer, void *userdata)
300{
301 AVCodecContext *avctx = userdata;
302 OHCodecDecContext *s = avctx->priv_data;
303 OHBufferQueueItem item = {
304 index, buffer,
305 };
306
307 ff_mutex_lock(&s->input_mutex);
308 int ret = av_fifo_write(s->input_queue, &item, 1);
309 if (ret >= 0)
310 ff_cond_signal(&s->input_cond);
311 ff_mutex_unlock(&s->input_mutex);
312
313 if (ret < 0)
314 oh_decode_on_err(codec, AV_ERR_NO_MEMORY, userdata);
315}
316
317static void oh_decode_on_output(OH_AVCodec *codec, uint32_t index,
318 OH_AVBuffer *buffer, void *userdata)
319{
320 AVCodecContext *avctx = userdata;
321 OHCodecDecContext *s = avctx->priv_data;
322 OHBufferQueueItem item = {
323 index, buffer,
324 };
325
326 ff_mutex_lock(&s->output_mutex);
327 int ret = av_fifo_write(s->output_queue, &item, 1);
328 if (ret >= 0)
329 ff_cond_signal(&s->output_cond);
330 ff_mutex_unlock(&s->output_mutex);
331
332 if (ret < 0)
333 oh_decode_on_err(codec, AV_ERR_NO_MEMORY, userdata);
334}
335
337{
338 int ret;
339 OH_AVErrCode err;
340 OH_AVCodecCallback cb = {
341 .onError = oh_decode_on_err,
342 .onStreamChanged = oh_decode_on_stream_changed,
343 .onNeedInputBuffer = oh_decode_on_need_input,
344 .onNewOutputBuffer = oh_decode_on_output,
345 };
346
347 err = OH_VideoDecoder_RegisterCallback(s->dec, cb, avctx);
348 if (err != AV_ERR_OK) {
349 ret = ff_oh_err_to_ff_err(err);
350 av_log(avctx, AV_LOG_ERROR, "Register callback failed, %d, %s\n",
351 err, av_err2str(ret));
352 return ret;
353 }
354 err = OH_VideoDecoder_Prepare(s->dec);
355 if (err != AV_ERR_OK) {
356 ret = ff_oh_err_to_ff_err(err);
357 av_log(avctx, AV_LOG_ERROR, "Prepare failed, %d, %s\n",
358 err, av_err2str(ret));
359 return ret;
360 }
361 err = OH_VideoDecoder_Start(s->dec);
362 if (err != AV_ERR_OK) {
363 ret = ff_oh_err_to_ff_err(err);
364 av_log(avctx, AV_LOG_ERROR, "Start failed, %d, %s\n",
365 err, av_err2str(ret));
366 return ret;
367 }
368
369 return 0;
370}
371
373{
374 OHCodecDecContext *s = avctx->priv_data;
375
376 // Initialize these fields first, so oh_decode_close can destroy them safely
377 int ret = ff_pthread_init(s, mutex_cond_offsets);
378 if (ret < 0)
379 return ret;
380
381 ret = oh_decode_create(s, avctx);
382 if (ret < 0)
383 return ret;
384 ret = oh_decode_set_format(s, avctx);
385 if (ret < 0)
386 return ret;
387
388 size_t fifo_size = 16;
389 s->input_queue = av_fifo_alloc2(fifo_size, sizeof(OHBufferQueueItem),
391 s->output_queue = av_fifo_alloc2(fifo_size, sizeof(OHBufferQueueItem),
393 if (!s->input_queue || !s->output_queue)
394 return AVERROR(ENOMEM);
395
396 ret = oh_decode_start(s, avctx);
397 if (ret < 0)
398 return ret;
399
400 return 0;
401}
402
404{
405 OHCodecDecContext *s = avctx->priv_data;
406
407 if (s->dec) {
408 /* Stop but don't destroy dec directly, to keep hardware frames on
409 * the fly valid.
410 */
411 OH_AVErrCode err = OH_VideoDecoder_Stop(s->dec);
412 if (err == AV_ERR_OK)
413 av_log(avctx, AV_LOG_DEBUG, "Stop decoder success\n");
414 else
415 av_log(avctx, AV_LOG_ERROR, "Stop decoder failed, %d, %s\n",
417 s->dec = NULL;
418 av_refstruct_unref(&s->dec_ref);
419 }
420
421 av_packet_unref(&s->pkt);
422
423 av_fifo_freep2(&s->input_queue);
424
425 av_fifo_freep2(&s->output_queue);
426
427 ff_pthread_free(s, mutex_cond_offsets);
428
429 return 0;
430}
431
432static void oh_buffer_release(void *opaque, uint8_t *data)
433{
434 if (!opaque)
435 return;
436
437 OHCodecBuffer *buffer = opaque;
438
439 if (buffer->buffer) {
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);
445 else
446 OH_VideoDecoder_FreeOutputBuffer(dec, buffer->index);
447 }
448
449 av_refstruct_unref(&buffer->dec_ref);
451}
452
454 OHBufferQueueItem *output,
455 const OH_AVCodecBufferAttr *attr)
456{
457 OHCodecDecContext *s = avctx->priv_data;
458
459 frame->width = s->width;
460 frame->height = s->height;
461 int ret = ff_decode_frame_props(avctx, frame);
462 if (ret < 0)
463 return ret;
464
465 frame->format = AV_PIX_FMT_OHCODEC;
467 if (!buffer)
468 return AVERROR(ENOMEM);
469
470 buffer->dec_ref = av_refstruct_ref(s->dec_ref);
471
472 buffer->index = output->index;
473 buffer->buffer = output->buffer;
474 frame->buf[0] = av_buffer_create((uint8_t *)buffer->buffer, 1,
477 if (!frame->buf[0]) {
479 return AVERROR(ENOMEM);
480 }
481 // Point to OH_AVBuffer
482 frame->data[3] = frame->buf[0]->data;
483 frame->pts = av_rescale_q(attr->pts, AV_TIME_BASE_Q, avctx->pkt_timebase);
484 frame->pkt_dts = AV_NOPTS_VALUE;
485
486 return 0;
487}
488
490 OHBufferQueueItem *output,
491 const OH_AVCodecBufferAttr *attr)
492{
493 OHCodecDecContext *s = avctx->priv_data;
494
495 frame->format = avctx->pix_fmt;
496 frame->width = s->width;
497 frame->height = s->height;
498 int ret = ff_get_buffer(avctx, frame, 0);
499 if (ret < 0)
500 return ret;
501
502 frame->pts = av_rescale_q(attr->pts, AV_TIME_BASE_Q, avctx->pkt_timebase);
503 frame->pkt_dts = AV_NOPTS_VALUE;
504
505 uint8_t *p = OH_AVBuffer_GetAddr(output->buffer);
506 if (!p) {
507 av_log(avctx, AV_LOG_ERROR, "Failed to get output buffer addr\n");
508 return AVERROR_EXTERNAL;
509 }
510
511 uint8_t *src[4] = {0};
512 int src_linesizes[4] = {0};
513
514 ret = av_image_fill_linesizes(src_linesizes, frame->format, s->stride);
515 if (ret < 0)
516 return ret;
517 ret = av_image_fill_pointers(src, frame->format, s->slice_height, p,
518 src_linesizes);
519 if (ret < 0)
520 return ret;
521 av_image_copy2(frame->data, frame->linesize, src, src_linesizes,
522 frame->format, frame->width, frame->height);
523
524 OH_AVErrCode err = OH_VideoDecoder_FreeOutputBuffer(s->dec, output->index);
525 if (err != AV_ERR_OK) {
526 ret = ff_oh_err_to_ff_err(err);
527 av_log(avctx, AV_LOG_ERROR, "FreeOutputBuffer failed, %d, %s\n", err,
528 av_err2str(ret));
529 return ret;
530 }
531
532 return 0;
533}
534
536 OHBufferQueueItem *output)
537{
538 OHCodecDecContext *s = avctx->priv_data;
539 OH_AVCodecBufferAttr attr;
540
541 OH_AVErrCode err = OH_AVBuffer_GetBufferAttr(output->buffer, &attr);
542 if (err != AV_ERR_OK)
543 return ff_oh_err_to_ff_err(err);
544
545 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
546 av_log(avctx, AV_LOG_DEBUG, "Buffer flag eos\n");
547 OH_VideoDecoder_FreeOutputBuffer(s->dec, output->index);
548 return AVERROR_EOF;
549 }
550
551 if (!s->got_stream_info) {
552 // This shouldn't happen, add a warning message.
553 av_log(avctx, AV_LOG_WARNING,
554 "decoder didn't notify stream info, try get format explicitly\n");
555
556 OH_AVFormat *format = OH_VideoDecoder_GetOutputDescription(s->dec);
557 if (!format) {
558 av_log(avctx, AV_LOG_ERROR, "GetOutputDescription failed\n");
559 return AVERROR_EXTERNAL;
560 }
561
563 OH_AVFormat_Destroy(format);
564 if (!s->got_stream_info)
565 return AVERROR_EXTERNAL;
566 }
567
568 if (s->output_to_window)
569 return oh_decode_wrap_hw_buffer(avctx, frame, output, &attr);
570 return oh_decode_wrap_sw_buffer(avctx, frame, output, &attr);
571}
572
574{
575 OHCodecDecContext *s = avctx->priv_data;
576 OH_AVErrCode err;
577 int ret;
578
579 if (!s->pkt.size && !s->eof_sent) {
580 OH_AVCodecBufferAttr attr = {
581 .flags = AVCODEC_BUFFER_FLAGS_EOS,
582 };
583 err = OH_AVBuffer_SetBufferAttr(input->buffer, &attr);
584 if (err != AV_ERR_OK)
585 return ff_oh_err_to_ff_err(err);
586 err = OH_VideoDecoder_PushInputBuffer(s->dec, input->index);
587 if (err != AV_ERR_OK)
588 return ff_oh_err_to_ff_err(err);
589 s->eof_sent = true;
590 return 0;
591 }
592
593 uint8_t *p = OH_AVBuffer_GetAddr(input->buffer);
594 int32_t n = OH_AVBuffer_GetCapacity(input->buffer);
595 if (!p || n <= 0) {
596 av_log(avctx, AV_LOG_ERROR,
597 "Failed to get buffer addr (%p) or capacity (%d)\n",
598 p, n);
599 return AVERROR_EXTERNAL;
600 }
601 n = FFMIN(s->pkt.size, n);
602 memcpy(p, s->pkt.data, n);
603
604 OH_AVCodecBufferAttr attr = {
605 .size = n,
606 .offset = 0,
607 .pts = av_rescale_q(s->pkt.pts, avctx->pkt_timebase,
609 .flags = (s->pkt.flags & AV_PKT_FLAG_KEY)
610 ? AVCODEC_BUFFER_FLAGS_SYNC_FRAME : 0,
611 };
612
613 err = OH_AVBuffer_SetBufferAttr(input->buffer, &attr);
614 if (err != AV_ERR_OK) {
615 ret = ff_oh_err_to_ff_err(err);
616 return ret;
617 }
618 err = OH_VideoDecoder_PushInputBuffer(s->dec, input->index);
619 if (err != AV_ERR_OK) {
620 ret = ff_oh_err_to_ff_err(err);
621 av_log(avctx, AV_LOG_ERROR, "Push input buffer failed, %d, %s\n",
622 err, av_err2str(ret));
623 return ret;
624 }
625
626 if (n < s->pkt.size) {
627 s->pkt.size -= n;
628 s->pkt.data += n;
629 } else {
630 av_packet_unref(&s->pkt);
631 }
632
633 return 0;
634}
635
637{
638 OHCodecDecContext *s = avctx->priv_data;
639
640 while (1) {
642 int ret;
643
644 // Try get output
645 ff_mutex_lock(&s->output_mutex);
646 while (!s->decode_status) {
647 if (av_fifo_read(s->output_queue, &buffer, 1) >= 0)
648 break;
649 // Only wait after send EOF
650 if (s->eof_sent && !s->decode_status)
651 ff_cond_wait(&s->output_cond, &s->output_mutex);
652 else
653 break;
654 }
655
656 ret = s->decode_status;
657 ff_mutex_unlock(&s->output_mutex);
658
659 // Got a frame
660 if (buffer.buffer)
661 return oh_decode_output_frame(avctx, frame, &buffer);
662 if (ret < 0)
663 return ret;
664
665 if (!s->pkt.size) {
666 /* fetch new packet or eof */
667 ret = ff_decode_get_packet(avctx, &s->pkt);
668 if (ret < 0 && ret != AVERROR_EOF)
669 return ret;
670 }
671
672 // Wait input buffer
673 ff_mutex_lock(&s->input_mutex);
674 while (!s->decode_status) {
675 if (av_fifo_read(s->input_queue, &buffer, 1) >= 0)
676 break;
677 ff_cond_wait(&s->input_cond, &s->input_mutex);
678 }
679
680 ret = s->decode_status;
681 ff_mutex_unlock(&s->input_mutex);
682
683 if (ret < 0)
684 return ret;
685
686 ret = oh_decode_send_pkt(avctx, &buffer);
687 if (ret < 0)
688 return ret;
689 }
690
691 return AVERROR(EAGAIN);
692}
693
695{
696 OHCodecDecContext *s = avctx->priv_data;
697
698 OH_VideoDecoder_Flush(s->dec);
699
700 ff_mutex_lock(&s->input_mutex);
701 ff_mutex_lock(&s->output_mutex);
702 av_fifo_reset2(s->input_queue);
703 av_fifo_reset2(s->output_queue);
704 s->decode_status = 0;
705 s->eof_sent = false;
706 ff_mutex_unlock(&s->output_mutex);
707 ff_mutex_unlock(&s->input_mutex);
708
709 OH_VideoDecoder_Start(s->dec);
710}
711
712static const AVCodecHWConfigInternal *const oh_hw_configs[] = {
713 &(const AVCodecHWConfigInternal) {
714 .public = {
715 .pix_fmt = AV_PIX_FMT_OHCODEC,
718 .device_type = AV_HWDEVICE_TYPE_OHCODEC,
719 },
720 .hwaccel = NULL,
721 },
722 NULL
723};
724
725#define VD (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM)
727 {"codec_name", "Select codec by name",
728 OFFSET(name), AV_OPT_TYPE_STRING, .flags = VD},
729 {"allow_sw", "Allow software decoding",
730 OFFSET(allow_sw), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD},
731 {NULL}
732};
733
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, \
740 };
741
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, \
748 .p.id = codec_id, \
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, \
758 .bsfs = bsf, \
759 .hw_configs = oh_hw_configs, \
760 .p.wrapper_name = "ohcodec", \
761 };
762
763#if CONFIG_H264_OH_DECODER
764DECLARE_OHCODEC_VDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb")
765#endif
766
767#if CONFIG_HEVC_OH_DECODER
768DECLARE_OHCODEC_VDEC(hevc, "H.265", AV_CODEC_ID_HEVC, "hevc_mp4toannexb")
769#endif
static const char *const format[]
Definition af_aiir.c:445
#define VD
Definition amfdec.c:787
static FILE * out
int32_t
Libavcodec external API header.
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
Set various frame properties from the codec context / packet data.
Definition decode.c:1598
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
Definition decode.c:254
int ff_set_sar(AVCodecContext *avctx, AVRational sar)
Check that the provided sample aspect ratio is valid and set it on the codec context.
Definition utils.c:106
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
static AVPacket * pkt
static AVFrame * frame
size_t fifo_size
Definition dts2pts.c:611
static SDL_Window * window
Definition ffplay.c:365
A generic FIFO API.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ 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:275
@ AV_CODEC_HW_CONFIG_METHOD_AD_HOC
The codec supports this format by some ad-hoc method.
Definition codec.h:311
@ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
The codec supports this format via the hw_device_ctx interface.
Definition codec.h:282
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition buffer.h:114
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.
Definition buffer.c:55
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
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
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
void av_fifo_reset2(AVFifo *f)
Definition fifo.c:280
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition rational.c:110
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.
Definition imgutils.c:145
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
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
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
int index
Definition gxfenc.c:90
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition hwcontext.c:120
@ AV_HWDEVICE_TYPE_OHCODEC
Definition hwcontext.h:43
misc image utilities
av_cold void ff_pthread_free(void *obj, const unsigned offsets[])
Definition pthread.c:92
av_cold int ff_pthread_init(void *obj, const unsigned offsets[])
Initialize/destroy a list of mutexes/conditions contained in a structure.
Definition pthread.c:105
#define av_cold
Definition attributes.h:117
static int ff_cond_wait(AVCond *cond, AVMutex *mutex)
Definition thread.h:198
static int ff_mutex_unlock(AVMutex *mutex)
Definition thread.h:189
static int ff_mutex_lock(AVMutex *mutex)
Definition thread.h:188
#define AVCond
Definition thread.h:192
static int ff_cond_signal(AVCond *cond)
Definition thread.h:196
#define AVMutex
Definition thread.h:184
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
const char data[16]
Definition mxf.c:149
enum AVPixelFormat ff_oh_pix_to_ff_pix(OH_AVPixelFormat oh_pix)
Definition ohcodec.c:63
int ff_oh_err_to_ff_err(OH_AVErrCode err)
Definition ohcodec.c:25
static const char * ff_oh_mime(enum AVCodecID codec_id, void *log)
Definition ohcodec.h:40
static av_cold int oh_decode_init(AVCodecContext *avctx)
Definition ohdec.c:372
#define DECLARE_OHCODEC_VDEC(short_name, full_name, codec_id, bsf)
Definition ohdec.c:742
static void oh_decode_on_need_input(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
Definition ohdec.c:298
static void oh_decode_on_err(OH_AVCodec *codec, int32_t err, void *userdata)
Definition ohdec.c:202
static int oh_decode_wrap_sw_buffer(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output, const OH_AVCodecBufferAttr *attr)
Definition ohdec.c:489
static void oh_decode_release(AVRefStructOpaque unused, void *obj)
Definition ohdec.c:88
static int oh_decode_set_format(OHCodecDecContext *s, AVCodecContext *avctx)
Definition ohdec.c:144
static int oh_decode_wrap_hw_buffer(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output, const OH_AVCodecBufferAttr *attr)
Definition ohdec.c:453
static int oh_decode_start(OHCodecDecContext *s, AVCodecContext *avctx)
Definition ohdec.c:336
static int oh_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Definition ohdec.c:636
static const AVCodecHWConfigInternal *const oh_hw_configs[]
Definition ohdec.c:712
static int oh_decode_output_frame(AVCodecContext *avctx, AVFrame *frame, OHBufferQueueItem *output)
Definition ohdec.c:535
static int oh_decode_create(OHCodecDecContext *s, AVCodecContext *avctx)
Definition ohdec.c:99
static void oh_decode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format, void *userdata)
Definition ohdec.c:219
static void oh_decode_flush(AVCodecContext *avctx)
Definition ohdec.c:694
static void oh_buffer_release(void *opaque, uint8_t *data)
Definition ohdec.c:432
static const AVOption ohcodec_vdec_options[]
Definition ohdec.c:726
#define OFFSET(x)
Definition ohdec.c:77
static void oh_decode_on_output(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userdata)
Definition ohdec.c:317
static int oh_decode_send_pkt(AVCodecContext *avctx, OHBufferQueueItem *input)
Definition ohdec.c:573
static av_cold int oh_decode_close(AVCodecContext *avctx)
Definition ohdec.c:403
AVOptions.
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_OHCODEC
Definition pixfmt.h:500
#define DEFINE_OFFSET_ARRAY(type, name, cnt_variable, mutexes, conds)
const char * name
Definition qsvenc.c:142
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition refstruct.c:140
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.
Definition refstruct.h:94
uint8_t * data
The data buffer.
Definition buffer.h:90
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition avcodec.h:681
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition avcodec.h:554
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
Definition avcodec.h:657
enum AVColorSpace colorspace
YUV colorspace type.
Definition avcodec.h:671
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition avcodec.h:664
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition avcodec.h:1494
enum AVCodecID codec_id
Definition avcodec.h:453
void * priv_data
Definition avcodec.h:470
Definition fifo.c:35
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition hwcontext.h:75
OpenHarmony codec device.
void * native_window
Pointer to OHNativeWindow.
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Rational number (pair of numerator and denominator).
Definition rational.h:58
OH_AVBuffer * buffer
Definition ohcodec.h:35
uint32_t index
Definition ohcodec.h:34
uint32_t index
Definition ohdec.c:83
OH_AVBuffer * buffer
Definition ohdec.c:84
OH_AVCodec ** dec_ref
RefStruct reference.
Definition ohdec.c:85
AVPacket pkt
Definition ohdec.c:59
AVClass * avclass
Definition ohdec.c:43
AVMutex input_mutex
Definition ohdec.c:51
AVCond input_cond
Definition ohdec.c:52
int decode_status
Definition ohdec.c:61
AVFifo * input_queue
Definition ohdec.c:53
AVCond output_cond
Definition ohdec.c:56
OH_AVPixelFormat pix_fmt
Definition ohdec.c:70
unsigned mutex_cond_cnt
Definition ohdec.c:74
AVFifo * output_queue
Definition ohdec.c:57
OH_AVCodec * dec
Definition ohdec.c:44
bool output_to_window
Definition ohdec.c:64
char * name
Definition ohdec.c:72
AVMutex output_mutex
Definition ohdec.c:55
OH_AVCodec ** dec_ref
Definition ohdec.c:49
bool got_stream_info
Definition ohdec.c:65
#define av_free(p)
#define av_mallocz(s)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static char buffer[20]
Definition seek.c:32
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
static double cb(void *priv, double x, double y)
Definition vf_geq.c:247