UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
libavcodec.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2013-2024 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif // HAVE_CONFIG_H
41
42#include <assert.h>
43#ifdef HAVE_SWSCALE
44#include <libswscale/swscale.h>
45#endif // defined HAVE_SWSCALE
46#include <limits.h>
47#include <stdbool.h>
48#include <stdio.h>
49#include <stdlib.h>
50
51#include "debug.h"
52#include "host.h"
53#include "lib_common.h"
57#include "rtp/rtpdec_h264.h"
58#include "rtp/rtpenc_h264.h"
59#include "tv.h"
60#include "utils/macros.h"
61#include "video.h"
62#include "video_codec.h"
63#include "video_decompress.h"
64
66#include "hwaccel_vaapi.h"
67#include "hwaccel_vdpau.h"
69
70#define MOD_NAME "[lavd] "
71
73 AVCodecContext *codec_ctx;
74 AVFrame *frame;
75 AVFrame *tmp_frame;
76 AVPacket *pkt;
77
79 int pitch;
80 int rgb_shift[3];
83 struct {
85 enum AVPixelFormat convert_in;
86 };
89
92 enum AVPixelFormat in_codec, out_codec;
93 struct SwsContext *ctx;
94 AVFrame *frame;
95 } sws;
96
98
100
102 long long mov_avg_frames;
104};
105
106static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const enum AVPixelFormat *fmt);
107
109{
111
112 if(s->codec_ctx) {
114 avcodec_free_context(&s->codec_ctx);
115 }
116 av_frame_free(&s->frame);
117 av_frame_free(&s->tmp_frame);
118 av_packet_free(&s->pkt);
119
121
122 s->convert_in = AV_PIX_FMT_NONE;
123
124#ifdef HAVE_SWSCALE
125 sws_freeContext(s->sws.ctx);
126 s->sws.ctx = NULL;
127 if (s->sws.frame) {
128 av_freep(s->sws.frame->data);
129 }
130 av_frame_free(&s->sws.frame);
131#endif // defined HAVE_SWSCALE
132}
133
134static int check_av_opt_set(void *state, const char *key, const char *val) {
135 int ret = av_opt_set(state, key, val, 0);
136 if (ret != 0) {
137 printf_libav_error(LOG_LEVEL_WARNING, ret, MOD_NAME "Unable to set %s to %s", key, val);
138 }
139 return ret;
140}
141
142ADD_TO_PARAM("lavd-thread-count", "* lavd-thread-count=<thread_count>[F][S][n][d]\n"
143 " Use <thread_count> decoding threads (0 is usually auto).\n"
144 " Flag 'F' enables frame parallelism (disabled by default), 'S' slice based, can be both (default slice), 'n' for none; 'd' - disable low delay\n");
146{
147 int thread_count = 0;
148 int req_thread_type = 0;
149 bool req_low_delay = true;
150 const char *thread_count_opt = get_commandline_param("lavd-thread-count");
151 if (thread_count_opt != NULL) {
152 char *endptr = NULL;
153 errno = 0;
154 long val = strtol(thread_count_opt, &endptr, 0);
155 if (errno == 0 && thread_count_opt[0] != '\0' && val >= 0 && val <= INT_MAX && (*endptr == '\0' || toupper(*endptr) == 'F' || toupper(*endptr) == 'S')) {
156 thread_count = val;
157 while (*endptr) {
158 switch (toupper(*endptr)) {
159 case 'F': req_thread_type |= FF_THREAD_FRAME; break;
160 case 'S': req_thread_type |= FF_THREAD_SLICE; break;
161 case 'n': req_thread_type = -1; break;
162 case 'd': req_low_delay = false; break;
163 }
164 endptr++;
165 }
166 } else {
167 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Wrong value for thread count: %s\n", thread_count_opt);
168 }
169 }
170
171 s->codec_ctx->thread_count = thread_count; // zero should mean count equal to the number of virtual cores
172 s->codec_ctx->thread_type = 0;
173 if (req_thread_type == 0) {
174 req_thread_type = FF_THREAD_SLICE;
175 } if (req_thread_type == -1) {
176 req_thread_type = 0;
177 }
178 if ((req_thread_type & FF_THREAD_FRAME) != 0U) {
179 if (s->codec_ctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
180 s->codec_ctx->thread_type |= FF_THREAD_FRAME;
181 } else {
182 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: Codec doesn't support frame-based multithreading but requested.\n");
183 }
184 }
185 if ((req_thread_type & FF_THREAD_SLICE) != 0U) {
186 if (s->codec_ctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
187 s->codec_ctx->thread_type |= FF_THREAD_SLICE;
188 } else {
189 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Warning: Codec doesn't support slice-based multithreading.\n");
190 }
191 }
192 log_msg(LOG_LEVEL_INFO, MOD_NAME "Setting thread count to %d, type: %s\n", s->codec_ctx->thread_count, lavc_thread_type_to_str(s->codec_ctx->thread_type));
193
194 s->codec_ctx->flags |= req_low_delay ? AV_CODEC_FLAG_LOW_DELAY : 0;
195 s->codec_ctx->flags2 |= AV_CODEC_FLAG2_FAST;
196 // set by decoder
197 s->codec_ctx->pix_fmt = AV_PIX_FMT_NONE;
198 // callback to negotiate pixel format that is supported by UG
199 s->codec_ctx->get_format = get_format_callback;
200 s->codec_ctx->opaque = s;
201
202 if (strstr(s->codec_ctx->codec->name, "cuvid") != NULL) {
203 char gpu[3];
204 snprintf(gpu, sizeof gpu, "%u", cuda_devices[0]);
205 check_av_opt_set(s->codec_ctx->priv_data, "gpu", gpu);
206 }
207}
208
209static void jpeg_callback(void)
210{
211 log_msg(LOG_LEVEL_WARNING, "[lavd] Warning: JPEG decoder "
212 "will use full-scale YUV.\n");
213}
214
215enum {
219};
220
223 enum AVCodecID avcodec_id;
224 void (*codec_callback)(void);
225 // Note:
226 // Make sure that if adding hw decoders to prefered_decoders[] that
227 // that decoder fails if there is not the HW during init, not while decoding
228 // frames (like vdpau does). Otherwise, such a decoder would be initialized
229 // but no frame decoded then.
230 // Note 2:
231 // cuvid decoders cannot be currently used as the default ones because they
232 // currently support only 4:2:0 subsampling and fail during decoding if other
233 // subsampling is given.
234 const char *preferred_decoders[MAX_PREFERED + 1]; // must be NULL-terminated
235};
236
237static const struct decoder_info decoders[] = {
238 { H264, AV_CODEC_ID_H264, NULL, { NULL /* "h264_cuvid" */ } },
239 { H265, AV_CODEC_ID_HEVC, NULL, { NULL /* "hevc_cuvid" */ } },
240 { MJPG, AV_CODEC_ID_MJPEG, jpeg_callback, { NULL } },
241 { JPEG, AV_CODEC_ID_MJPEG, jpeg_callback, { NULL } },
242 { J2K, AV_CODEC_ID_JPEG2000, NULL, { NULL } },
243 { J2KR, AV_CODEC_ID_JPEG2000, NULL, { NULL } },
244 { VP8, AV_CODEC_ID_VP8, NULL, { NULL } },
245 { VP9, AV_CODEC_ID_VP9, NULL, { NULL } },
246 { HFYU, AV_CODEC_ID_HUFFYUV, NULL, { NULL } },
247 { FFV1, AV_CODEC_ID_FFV1, NULL, { NULL } },
248 { AV1, AV_CODEC_ID_AV1, NULL, { "libdav1d" } },
249 { PRORES_4444, AV_CODEC_ID_PRORES, NULL, { NULL } },
250 { PRORES_4444_XQ, AV_CODEC_ID_PRORES, NULL, { NULL } },
251 { PRORES_422_HQ, AV_CODEC_ID_PRORES, NULL, { NULL } },
252 { PRORES_422, AV_CODEC_ID_PRORES, NULL, { NULL } },
253 { PRORES_422_PROXY, AV_CODEC_ID_PRORES, NULL, { NULL } },
254 { PRORES_422_LT, AV_CODEC_ID_PRORES, NULL, { NULL } },
255 { CFHD, AV_CODEC_ID_CFHD, NULL, { NULL } }
256};
257
258static bool
260 enum AVCodecID avcodec_id,
261 const char *const preferred_decoders[static MAX_PREFERED + 1],
262 const AVCodec *usable_decoders[static DEC_LEN])
263{
264 unsigned int codec_index = 0;
265 // first try codec specified from cmdline if any
266 const char *param = get_commandline_param("force-lavd-decoder");
267 if (param != NULL) {
268 char *val = alloca(strlen(param) + 1);
269 strcpy(val, param);
270 char *item = NULL;
271 char *save_ptr = NULL;
272 while ((item = strtok_r(val, ":", &save_ptr))) {
273 val = NULL;
274 const AVCodec *codec =
275 avcodec_find_decoder_by_name(item);
276 if (codec == NULL) {
279 "Forced decoder not found: %s\n",
280 item);
281 exit_uv(1);
282 return false;
283 }
284 if (codec->id != avcodec_id) {
285 log_msg(
288 "Forced decoder not valid for codec: %s\n",
289 item);
290 continue;
291 }
292 assert(codec_index < MAX_DECODERS);
293 usable_decoders[codec_index++] = codec;
294 }
295 }
296 // then try preferred codecs
297 const char *const *preferred_decoders_it = preferred_decoders;
298 while (*preferred_decoders_it) {
299 const AVCodec *codec =
300 avcodec_find_decoder_by_name(*preferred_decoders_it);
301 if (codec == NULL) {
303 "[lavd] Decoder not available: %s\n",
304 *preferred_decoders_it);
305 preferred_decoders_it++;
306 continue;
307 }
308 assert(codec_index < MAX_DECODERS);
309 preferred_decoders_it++;
310 }
311 // finally, add a default one if there are no preferred enc. or all fail
312 assert(codec_index < MAX_DECODERS);
313 const AVCodec *default_decoder = avcodec_find_decoder(avcodec_id);
314 if (default_decoder == NULL) {
316 "[lavd] No decoder found for the input codec "
317 "(libavcodec perhaps compiled without any)!\n"
318 "Use \"--param force-lavd-decoder=<d> to select a "
319 "different decoder than libavcodec if there is "
320 "any eligibe.\n");
321 } else {
322 usable_decoders[codec_index++] = default_decoder;
323 }
324 usable_decoders[codec_index] = NULL;
325 return true;
326}
327
328ADD_TO_PARAM("force-lavd-decoder", "* force-lavd-decoder=<decoder>[:<decoder2>...]\n"
329 " Forces specified Libavcodec decoder. If more need to be specified, use colon as a delimiter.\n"
330 " Use '-c libavcodec:help' to see available decoders.\n");
331
332ADD_TO_PARAM("use-hw-accel", "* use-hw-accel[=<api>|help]\n"
333 " Try to use hardware accelerated decoding with lavd "
334 "(NVDEC/VAAPI/VDPAU/VideoToolbox).\n"
335 " Optionally with enforced API option.\n");
337 struct video_desc desc, void *extradata, int extradata_size)
338{
339 const struct decoder_info *dec = NULL;
340
342
343 for (unsigned int i = 0; i < sizeof decoders / sizeof decoders[0]; ++i) {
344 if (decoders[i].ug_codec == desc.color_spec) {
345 dec = &decoders[i];
346 break;
347 }
348 }
349
350 if (dec == NULL) {
351 log_msg(LOG_LEVEL_ERROR, "[lavd] Unsupported codec!!!\n");
352 return false;
353 }
354
355 if (dec->codec_callback) {
356 dec->codec_callback();
357 }
358
359 // priority list of decoders that can be used for the codec
360 const AVCodec *usable_decoders[DEC_LEN] = { NULL };
361 if (!get_usable_decoders(dec->avcodec_id, dec->preferred_decoders,
362 usable_decoders)) {
363 return false;
364 }
365
366 // initialize the codec - use the first decoder initialization of which succeeds
367 const AVCodec **codec_it = usable_decoders;
368 while (*codec_it) {
369 log_msg(LOG_LEVEL_VERBOSE, "[lavd] Trying decoder: %s\n", (*codec_it)->name);
370 s->codec_ctx = avcodec_alloc_context3(*codec_it);
371 if(s->codec_ctx == NULL) {
372 log_msg(LOG_LEVEL_ERROR, "[lavd] Unable to allocate codec context.\n");
373 return false;
374 }
375 if (extradata) {
376 s->codec_ctx->extradata = malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
377 memcpy(s->codec_ctx->extradata, extradata, extradata_size);
378 s->codec_ctx->extradata_size = extradata_size;
379 }
380 s->codec_ctx->width = desc.width;
381 s->codec_ctx->height = desc.height;
383 s->codec_ctx->codec_tag = get_fourcc(desc.color_spec);
384 }
386 if (avcodec_open2(s->codec_ctx, *codec_it, NULL) < 0) {
387 avcodec_free_context(&s->codec_ctx);
388 log_msg(LOG_LEVEL_WARNING, "[lavd] Unable to open decoder %s.\n", (*codec_it)->name);
389 codec_it++;
390 continue;
391 }
392 log_msg(LOG_LEVEL_NOTICE, "[lavd] Using decoder: %s\n", (*codec_it)->name);
393 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Codec %s capabilities: 0x%08X; using thread type %d, count %d\n",
394 (*codec_it)->name, (*codec_it)->capabilities, s->codec_ctx->thread_type, s->codec_ctx->thread_count);
395 break;
396 }
397
398 if (s->codec_ctx == NULL) {
399 log_msg(LOG_LEVEL_ERROR, "[lavd] Decoder could have not been initialized for codec %s.\n",
401 return false;
402 }
403
404 s->frame = av_frame_alloc();
405 s->tmp_frame = av_frame_alloc();
406 if (s->frame == NULL || s->tmp_frame == NULL) {
407 log_msg(LOG_LEVEL_ERROR, "[lavd] Unable allocate frame.\n");
408 return false;
409 }
410
411 s->pkt = av_packet_alloc();
412
413 return true;
414}
415
417static bool
419{
420 const char *const hwaccel = get_commandline_param("use-hw-accel");
421 if (hwaccel == NULL) {
422 return true;
423 }
424#if !defined HWACC_COMMON_IMPL
425 MSG(FATAL, "HW acceleration not compiled in!\n");
426 exit_uv(1);
427 return NULL;
428#endif
429 if (strlen(hwaccel) == 0 ||
430 hw_accel_from_str(hwaccel) != HWACCEL_NONE) {
431 return true;
432 }
433 if (strcmp(hwaccel, "help") == 0) {
434 exit_uv(0);
435 return false;
436 }
437 MSG(ERROR, "Wrong HW acceleration specified: %s\n", hwaccel);
438 exit_uv(1);
439 return false;
440}
441
442static void * libavcodec_decompress_init(void)
443{
444 if (!validate_hwacc_param()) {
445 return NULL;
446 }
447
449 calloc(1, sizeof(struct state_libavcodec_decompress));
450
452
453#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(58, 9, 100)
454 /* register all the codecs (you can also register only the codec
455 * you wish to have smaller code */
456 avcodec_register_all();
457#endif
458
460
461 return s;
462}
463
465 int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
466{
469
470 s->pitch = pitch;
471 s->rgb_shift[R_SHIFT_IDX] = rshift;
472 s->rgb_shift[G_SHIFT_IDX] = gshift;
473 s->rgb_shift[B_SHIFT_IDX] = bshift;
474 for(int i = 0; i < HWACCEL_COUNT; i++){
475 s->block_accel[i] = get_commandline_param("use-hw-accel") == NULL;
476 }
477 s->out_codec = out_codec;
478 s->desc = desc;
479
480 deconfigure(s);
482 // for codecs that have metadata we have to defer initialization
483 // because we don't have the data right now
484 return true;
485 }
486 return configure_with(s, desc, NULL, 0);
487}
488
489#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 75, 100)
490static int drm_prime_init(struct AVCodecContext *s,
491 struct hw_accel_state *state,
493{
495 state->type = HWACCEL_DRM_PRIME;
496 AVBufferRef *ref = NULL;
497 int ret = create_hw_device_ctx(AV_HWDEVICE_TYPE_DRM, &ref);
498 if(ret < 0)
499 return ret;
500
501 s->hw_device_ctx = ref;
502 state->copy = out_codec != DRM_PRIME;
503 state->tmp_frame = av_frame_alloc();
504 if(!state->tmp_frame){
505 av_buffer_unref(&ref);
506 return -1;
507 }
508 return 0;
509}
510#endif
511
512#if defined HWACC_COMMON_IMPL && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 39, 100)
513static int vulkan_init(struct AVCodecContext *s,
514 struct hw_accel_state *state,
516{
518
519 AVBufferRef *device_ref = NULL;
520 int ret = create_hw_device_ctx(AV_HWDEVICE_TYPE_VULKAN, &device_ref);
521 if(ret < 0)
522 return ret;
523
524 state->tmp_frame = av_frame_alloc();
525 if(!state->tmp_frame){
526 ret = -1;
527 goto fail;
528 }
529
530 s->hw_device_ctx = device_ref;
531 state->type = HWACCEL_VULKAN;
532 state->copy = true;
533 return 0;
534
535fail:
536 av_frame_free(&state->tmp_frame);
537 av_buffer_unref(&device_ref);
538 return ret;
539}
540#endif
541
542#ifdef HWACC_COMMON_IMPL
543static int hwacc_cuda_init(struct AVCodecContext *s, struct hw_accel_state *state, codec_t out_codec)
544{
546
547 AVBufferRef *device_ref = NULL;
548 int ret = create_hw_device_ctx(AV_HWDEVICE_TYPE_CUDA, &device_ref);
549 if(ret < 0)
550 return ret;
551
552 state->tmp_frame = av_frame_alloc();
553 if(!state->tmp_frame){
554 ret = -1;
555 goto fail;
556 }
557
558 s->hw_device_ctx = device_ref;
559 state->type = HWACCEL_CUDA;
560 state->copy = true;
561
562 return 0;
563
564fail:
565 av_frame_free(&state->tmp_frame);
566 av_buffer_unref(&device_ref);
567 return ret;
568}
569#endif
570
571#ifdef HWACC_COMMON_IMPL
572static void
573check_pixfmt_hw_eligibility(enum AVPixelFormat sw_pix_fmt)
574{
575 const char *fmt_name = av_get_pix_fmt_name(sw_pix_fmt);
576 const int depth = av_pix_fmt_desc_get(sw_pix_fmt)->comp[0].depth;
577 if (depth != 8) {
578 MSG(WARNING,
579 "HW acceleration requested "
580 "but incoming video has %d bit depth (%s), which is more "
581 "than "
582 "universally supported 8b.\n",
583 depth, fmt_name);
584 }
585 if (av_pixfmt_get_subsampling(sw_pix_fmt) != SUBS_420) {
587 "[lavd] Hw. acceleration requested "
588 "but incoming video has not 4:2:0 subsampling (format "
589 "is %s), "
590 "which is usually not supported by hw. accelerators\n",
591 fmt_name);
592 }
593}
594#endif
595
596static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
597{
598#define SELECT_PIXFMT(pixfmt) { log_msg(LOG_LEVEL_INFO, MOD_NAME "Selected pixel format: %s\n", av_get_pix_fmt_name(pixfmt)); return pixfmt; }
599 MSG(VERBOSE, "Available output pixel formats: %s\n",
601
603 const char *hwaccel = get_commandline_param("use-hw-accel");
604#ifdef HWACC_COMMON_IMPL
605 hwaccel_state_reset(&state->hwaccel);
606
607 static const struct{
608 enum AVPixelFormat pix_fmt;
609 int (*init_func)(AVCodecContext *, struct hw_accel_state *, codec_t);
610 } accels[] = {
611#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 39, 100)
612 {AV_PIX_FMT_VULKAN, vulkan_init},
613#endif
614#ifdef HWACC_VDPAU
615 {AV_PIX_FMT_VDPAU, vdpau_init},
616#endif
617 {AV_PIX_FMT_CUDA, hwacc_cuda_init},
618#ifdef HWACC_VAAPI
619 {AV_PIX_FMT_VAAPI, vaapi_init},
620#endif
621#ifdef __APPLE__
622 {AV_PIX_FMT_VIDEOTOOLBOX, videotoolbox_init},
623#endif
624#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 75, 100)
625 {AV_PIX_FMT_DRM_PRIME, drm_prime_init},
626#endif
627 {AV_PIX_FMT_NONE, NULL}
628 };
629
630 if (hwaccel != NULL) {
631 struct state_libavcodec_decompress *state = (struct state_libavcodec_decompress *) s->opaque;
632 check_pixfmt_hw_eligibility(s->sw_pix_fmt);
633 const enum hw_accel_type forced_hwaccel =
634 strlen(hwaccel) > 0 ? hw_accel_from_str(hwaccel)
635 : HWACCEL_NONE;
636 for(const enum AVPixelFormat *it = fmt; *it != AV_PIX_FMT_NONE; it++){
637 for(unsigned i = 0; i < sizeof(accels) / sizeof(accels[0]); i++){
638 if (*it != accels[i].pix_fmt ||
639 state->block_accel[hw_accel_from_pixfmt(accels[i].pix_fmt)]) {
640 continue;
641 }
642 if (forced_hwaccel != HWACCEL_NONE &&
643 hw_accel_from_pixfmt(accels[i].pix_fmt) !=
644 forced_hwaccel) {
645 break;
646 }
647 int ret = accels[i].init_func(s, &state->hwaccel, state->out_codec);
648 if(ret < 0){
649 hwaccel_state_reset(&state->hwaccel);
650 break;
651 }
652 SELECT_PIXFMT(accels[i].pix_fmt);
653 }
654 }
655 if(forced_hwaccel != HWACCEL_NONE){
656 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Requested hw accel \"%s\" is not available\n", hwaccel);
657 return AV_PIX_FMT_NONE;
658 }
659 log_msg(LOG_LEVEL_WARNING, "[lavd] Falling back to software decoding!\n");
660 if (state->out_codec == HW_VDPAU) {
661 return AV_PIX_FMT_NONE;
662 }
663 }
664#endif
665
666 if (state->out_codec == VIDEO_CODEC_NONE) { // probe
668 if (c != VIDEO_CODEC_NONE) {
669 enum AVPixelFormat selected_fmt = lavd_get_av_to_ug_codec(fmt, c, hwaccel);
670 return selected_fmt;
671 }
672 } else {
673 enum AVPixelFormat f = lavd_get_av_to_ug_codec(fmt, state->out_codec, hwaccel);
674 if (f != AV_PIX_FMT_NONE) {
675 SELECT_PIXFMT(f);
676 }
677 }
678
679#ifdef HAVE_SWSCALE
680 for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) {
681 const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(*fmt_it);
682 if (fmt_desc && (fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) == 0U) {
683 SELECT_PIXFMT(*fmt_it);
684 }
685 }
686#endif
687
688 return AV_PIX_FMT_NONE;
689}
690
691#ifdef HAVE_SWSCALE
692static bool lavd_sws_convert_reconfigure(struct state_libavcodec_decompress_sws *sws, enum AVPixelFormat sws_in_codec,
693 enum AVPixelFormat sws_out_codec, int width, int height)
694{
695 if (sws->width == width && sws->height == height && sws->in_codec == sws_in_codec && sws->ctx != NULL) {
696 return true;
697 }
698 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Using swscale to convert from %s to %s.\n",
699 av_get_pix_fmt_name(sws_in_codec), av_get_pix_fmt_name(sws_out_codec));
700 sws_freeContext(sws->ctx);
701 if (sws->frame) {
702 av_freep(sws->frame->data);
703 }
704 av_frame_free(&sws->frame);
705 sws->ctx = getSwsContext(width, height, sws_in_codec,
706 width, height, sws_out_codec,
707 SWS_POINT);
708 if(!sws->ctx){
709 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to init sws context.\n");
710 return false;
711 }
712 sws->frame = av_frame_alloc();
713 if (!sws->frame) {
714 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate sws frame\n");
715 return false;
716 }
717 sws->frame->width = width;
718 sws->frame->height = height;
719 sws->frame->format = sws_out_codec;
720 int ret = av_image_alloc(sws->frame->data, sws->frame->linesize,
721 sws->frame->width, sws->frame->height,
722 sws_out_codec, 32);
723 if (ret < 0) {
724 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate raw picture buffer for sws\n");
725 return false;
726 }
727 sws->width = width;
728 sws->height = height;
729 sws->in_codec = sws_in_codec;
730 sws->out_codec = sws_out_codec;
731
732 return true;
733}
734
735static void lavd_sws_convert(struct state_libavcodec_decompress_sws *sws, AVFrame *in_frame)
736{
737 sws_scale(sws->ctx,
738 (const uint8_t * const *) in_frame->data,
739 in_frame->linesize,
740 0,
741 in_frame->height,
742 sws->frame->data,
743 sws->frame->linesize);
744}
745
748static void lavd_sws_convert_to_buffer(struct state_libavcodec_decompress_sws *sws,
749 AVFrame *in_frame, char *out_buffer)
750{
751 struct AVFrame *out = av_frame_alloc();
752 codec_t ug_out_pixfmt = get_av_to_ug_pixfmt(sws->frame->format);
753 if (codec_is_planar(ug_out_pixfmt)) {
754 buf_get_planes(sws->frame->width, sws->frame->height, ug_out_pixfmt, out_buffer, (char **) out->data);
755 buf_get_linesizes(sws->frame->width, ug_out_pixfmt, out->linesize);
756 } else {
757 out->data[0] = (unsigned char *) out_buffer;
758 out->linesize[0] = vc_get_linesize(sws->frame->width, ug_out_pixfmt);
759 }
760
761 sws_scale(sws->ctx,
762 (const uint8_t * const *) in_frame->data,
763 in_frame->linesize,
764 0,
765 in_frame->height,
766 out->data,
767 out->linesize);
768 av_frame_free(&out);
769}
770#endif
771
772static _Bool reconfigure_convert_if_needed(struct state_libavcodec_decompress *s, enum AVPixelFormat av_codec, codec_t out_codec, int width, int height) {
773 assert(av_codec != AV_PIX_FMT_NONE);
774 if (s->convert_in == av_codec) {
775 return 1;
776 }
778 s->convert = get_av_to_uv_conversion(av_codec, out_codec);
779 if (s->convert != NULL) {
780 s->convert_in = av_codec;
781 return 1;
782 }
783#ifdef HAVE_SWSCALE
784 if (get_ug_to_av_pixfmt(out_codec) != AV_PIX_FMT_NONE) { // the UG pixfmt can be used directly as dst for sws
785 if (!lavd_sws_convert_reconfigure(&s->sws, av_codec, get_ug_to_av_pixfmt(out_codec), width, height)) {
786 return 0;
787 }
788 s->convert_in = av_codec;
789 return 1;
790 }
791
792 // else try to find swscale
793 enum AVPixelFormat sws_out_codec = pick_av_convertible_to_ug(out_codec, &s->convert);
794 if (!sws_out_codec) {
795 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unsupported pixel format: %s (id %d)\n",
796 av_get_pix_fmt_name(av_codec), av_codec);
797 return 0;
798 }
799 if (!lavd_sws_convert_reconfigure(&s->sws, av_codec, sws_out_codec, width, height)) {
800 return 0;
801 }
802 s->convert_in = av_codec;
803 return 1;
804#else
805 UNUSED(width), UNUSED(height);
806 return 0;
807#endif
808}
809
822static void
823change_pixfmt(AVFrame *frame, unsigned char *dst, av_to_uv_convert_t *convert,
824 codec_t out_codec, int width, int height, int pitch,
825 int rgb_shift[static restrict 3],
826 struct state_libavcodec_decompress_sws *sws)
827{
829
830 if (!sws->ctx) {
831 av_to_uv_convert(convert, (char *) dst, frame, width, height,
832 pitch, rgb_shift);
833 return;
834 }
835
836#ifdef HAVE_SWSCALE
837 if (get_ug_to_av_pixfmt(out_codec) != AV_PIX_FMT_NONE) { // the UG pixfmt can be used directly as dst for sws
838 lavd_sws_convert_to_buffer(sws, frame, (char *) dst);
839 return;
840 }
841
842 lavd_sws_convert(sws, frame);
843 av_to_uv_convert(convert, (char *) dst, sws->frame, width, height,
844 pitch, rgb_shift);
845#else
846 (void) out_codec;
847#endif // HAVE_SWSCALE
848}
849
860static _Bool check_first_sps_vps(struct state_libavcodec_decompress *s, unsigned char *src, unsigned int src_len) {
861 if (s->sps_vps_found) {
862 return 1;
863 }
864 _Thread_local static time_ns_t t0;
865 if (t0 == 0) {
866 t0 = get_time_in_ns();
867 }
868 if (get_time_in_ns() - t0 > 10 * NS_IN_SEC) { // after 10 seconds surrender and let decoder do the job
869 log_msg(LOG_LEVEL_WARNING, MOD_NAME "No SPS found, starting decode, anyway. Please report a bug to " PACKAGE_BUGREPORT " if decoding succeeds from now.\n");
870 s->sps_vps_found = 1;
871 return 1;
872 }
873
874 const unsigned char *const nal =
875 rtpenc_get_first_nal(src, src_len, s->desc.color_spec == H265);
876 if (nal == NULL) {
877 return 0;
878 }
879 const int nalu_type =
880 NALU_HDR_GET_TYPE(nal[0], s->desc.color_spec == H265);
881
882 switch (nalu_type) {
883 case NAL_H264_SPS:
884 case NAL_HEVC_VPS:
885 s->sps_vps_found = 1;
887 MOD_NAME "Received %s NALU, decoding begins.\n",
888 get_nalu_name(nalu_type));
889 return 1;
890 default:
892 MOD_NAME "Waiting for first SPS/VPS NALU...\n");
893 return 0;
894 }
895}
896
898static void check_duration(struct state_libavcodec_decompress *s, double duration_total_sec, double duration_pixfmt_change_sec)
899{
900 enum {
901 MOV_WIN_FRM = 100,
902 REPEAT_INT_SEC = 30,
903 TIME_SLOT_PERC_MAX = 66
904 };
905 double tpf = 1 / s->desc.fps;
906 tpf *= TIME_SLOT_PERC_MAX / 100.;
908 (s->mov_avg_comp_duration * (MOV_WIN_FRM - 1) +
909 duration_total_sec) /
910 MOV_WIN_FRM;
911 s->mov_avg_frames += 1;
912 if (s->mov_avg_frames < 2 * MOV_WIN_FRM ||
913 s->mov_avg_comp_duration < tpf) {
914 return;
915 }
916 const time_ns_t now = get_time_in_ns();
917 if (now < s->duration_warn_last_print + NS_IN_SEC * REPEAT_INT_SEC) {
918 return;
919 }
921 MSG(WARNING,
922 "Avg decompress time of last %d frames is %.2f ms which exceeds %.2f "
923 "ms (%d%% of TPF)!\n",
924 MOV_WIN_FRM, s->mov_avg_comp_duration * MS_IN_SEC, tpf * MS_IN_SEC,
925 TIME_SLOT_PERC_MAX);
926 const char *hint = NULL;
927 if ((s->codec_ctx->thread_type & FF_THREAD_FRAME) == 0 &&
928 (s->codec_ctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) !=
929 0) {
930 hint = "\"--param lavd-thread-count=<n>FS\" option with small <n> or 0 (nr of logical cores)";
931 } else if (s->codec_ctx->thread_count == 1 && (s->codec_ctx->codec->capabilities & AV_CODEC_CAP_OTHER_THREADS) != 0) {
932 hint = "\"--param lavd-thread-count=<n>\" option with small <n> or 0 (nr of logical cores)";
933 }
934 if (hint) {
935 MSG(WARNING,
936 "Consider adding %s to increase throughput at the expense "
937 "of latency.\n",
938 hint);
939 }
940 if ((s->codec_ctx->flags & AV_CODEC_FLAG_LOW_DELAY) != 0) {
941 MSG(WARNING,
942 "Consider %sdisabling low delay decode using 'd' flag.\n",
943 hint != NULL ? "also " : "");
944 }
945
946 bool in_rgb = av_pix_fmt_desc_get(s->convert_in)->flags & AV_PIX_FMT_FLAG_RGB;
947 if (codec_is_a_rgb(s->out_codec) != in_rgb && duration_pixfmt_change_sec > s->mov_avg_comp_duration / 4) {
948 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Also pixfmt change of last frame took %f ms.\n"
949 "Consider adding \"--conv-policy cds\" to prevent color space conversion.\n", duration_pixfmt_change_sec / 1000.0);
950 }
951}
952
953static void
954handle_lavd_error(const char *prefix, struct state_libavcodec_decompress *s,
955 int ret)
956{
957 print_decoder_error(prefix, ret);
958 if(ret == AVERROR(EIO)){
960 if(s->consecutive_failed_decodes > 70 && !s->block_accel[s->hwaccel.type]){
961 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Decode failing, "
962 " blacklisting hw. accelerator...\n");
963 s->block_accel[s->hwaccel.type] = true;
964 deconfigure(s);
965 configure_with(s, s->desc, NULL, 0);
966 }
967 } else if (ret == AVERROR(EAGAIN) && strcmp(s->codec_ctx->codec->name, "hevc_qsv") == 0) {
968 if (s->consecutive_failed_decodes++ == 70) {
969 log_msg(LOG_LEVEL_ERROR, MOD_NAME "hevc_qsv decoder keeps failing, which may be caused by intra refresh period.\n"
970 "Try disabling intra refresh on encoder: `-c libavcodec:encoder=libx265:disable_intra_refresh`\n");
971 }
972 }
973}
974
975static bool
976read_forced_pixfmt(codec_t compress, const unsigned char *src,
977 unsigned int src_len, struct pixfmt_desc *internal_props)
978{
979 if (compress == H264) {
980 char expected_prefix[] = { START_CODE_3B, H264_NAL_SEI_PREFIX, sizeof (unsigned char[]) { UG_ORIG_FORMAT_ISO_IEC_11578_GUID } + 1, UG_ORIG_FORMAT_ISO_IEC_11578_GUID };
981 if (src_len < sizeof expected_prefix + 2 || memcmp(src + src_len - sizeof expected_prefix - 2, expected_prefix, sizeof expected_prefix) != 0) {
982 return false;
983 }
984 } else if (compress == H265) {
985 char expected_prefix[] = { START_CODE_3B, HEVC_NAL_SEI_PREFIX, sizeof (unsigned char []) { UG_ORIG_FORMAT_ISO_IEC_11578_GUID } + 1, UG_ORIG_FORMAT_ISO_IEC_11578_GUID };
986 if (src_len < sizeof expected_prefix + 2 || memcmp(src + src_len - sizeof expected_prefix - 2, expected_prefix, sizeof expected_prefix) != 0) {
987 return false;
988 }
989 } else {
990 return false;
991 }
992 unsigned format = src[src_len - 2];
993 internal_props->depth = 8 + (format >> 4) * 2;
994 int subs_a = ((format >> 2) & 0x3) + 1;
995 int subs_b = ((format >> 1) & 0x1) * subs_a;
996 internal_props->subsampling = 4000 + subs_a * 100 + subs_b * 10;
997 internal_props->rgb = format & 0x1;
998 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Stream properties read from metadata.\n");
999 return true;
1000}
1001
1002static bool
1003decode_frame(struct state_libavcodec_decompress *s, unsigned char *src,
1004 int src_len)
1005{
1006 bool frame_decoded = false;
1007 s->pkt->data = src;
1008 s->pkt->size = src_len;
1009 int ret = avcodec_send_packet(s->codec_ctx, s->pkt);
1010 if (ret != 0 && ret != AVERROR(EAGAIN)) {
1011 handle_lavd_error(MOD_NAME "send - ", s, ret);
1012 return false;
1013 }
1014 // we output to tmp_frame because even if receive fails,
1015 // it overrides previous potentially valid frame
1016 while ((ret = avcodec_receive_frame(s->codec_ctx, s->tmp_frame)) == 0) {
1017 if (frame_decoded) {
1019 MOD_NAME "Multiple frames decoded at once!\n");
1020 }
1021 frame_decoded = true;
1022 SWAP_PTR(s->frame, s->tmp_frame);
1023 }
1024 if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
1025 handle_lavd_error(MOD_NAME "recv - ", s, ret);
1026 }
1027 return frame_decoded;
1028}
1029
1030static decompress_status libavcodec_decompress(void *state, unsigned char *dst, unsigned char *src,
1031 unsigned int src_len, int frame_seq, struct video_frame_callbacks *callbacks, struct pixfmt_desc *internal_props)
1032{
1033 UNUSED(frame_seq);
1035
1036 if (s->desc.color_spec == H264 || s->desc.color_spec == H265) {
1037 if (s->out_codec == VIDEO_CODEC_NONE &&
1038 read_forced_pixfmt(s->desc.color_spec, src, src_len,
1039 internal_props)) {
1040 return DECODER_GOT_CODEC;
1041 }
1042 if (!check_first_sps_vps(s, src, src_len)) {
1043 return DECODER_NO_FRAME;
1044 }
1045 }
1046
1048 int extradata_size = *(uint32_t *)(void *) src;
1049 if (s->codec_ctx == NULL) {
1050 if (!configure_with(s, s->desc, src + sizeof(uint32_t),
1051 extradata_size)) {
1052 return DECODER_NO_FRAME;
1053 }
1054 }
1055 src += extradata_size + sizeof(uint32_t);
1056 src_len -= extradata_size + sizeof(uint32_t);
1057 }
1058
1060
1061 if (!decode_frame(s, src, src_len)) {
1062 log_msg(LOG_LEVEL_DEBUG, MOD_NAME "No frame was decoded!\n");
1063 return DECODER_NO_FRAME;
1064 }
1066
1068
1069 s->frame->opaque = callbacks;
1070#ifdef HWACC_COMMON_IMPL
1071 if(s->hwaccel.copy){
1072 transfer_frame(&s->hwaccel, s->frame);
1073 }
1074#endif
1075 if (s->out_codec != VIDEO_CODEC_NONE) {
1076 if (!reconfigure_convert_if_needed(s, s->frame->format, s->out_codec, s->desc.width, s->desc.height)) {
1077 return DECODER_UNSUPP_PIXFMT;
1078 }
1079 change_pixfmt(s->frame, dst, s->convert, s->out_codec,
1080 s->desc.width, s->desc.height, s->pitch,
1081 s->rgb_shift, &s->sws);
1082 }
1084 log_msg(LOG_LEVEL_DEBUG, MOD_NAME "Decompressing %c frame took %f ms, pixfmt change %f ms.\n", av_get_picture_type_char(s->frame->pict_type),
1085 NS_TO_MS((double) (t1 - t0)), NS_TO_MS((double) (t2 - t1)));
1086 check_duration(s, (t2 - t0) / NS_IN_SEC_DBL, (t2 - t1) / NS_IN_SEC_DBL);
1087
1088 if (s->out_codec == VIDEO_CODEC_NONE) {
1090 MOD_NAME "Probed output pixel format: %s (%s)\n",
1091 av_get_pix_fmt_name(s->codec_ctx->pix_fmt),
1092 av_get_pix_fmt_name(s->codec_ctx->sw_pix_fmt));
1093 enum AVPixelFormat sw_fmt = s->codec_ctx->sw_pix_fmt == AV_PIX_FMT_NONE ? s->codec_ctx->pix_fmt : s->codec_ctx->sw_pix_fmt;
1094 *internal_props = av_pixfmt_get_desc(sw_fmt);
1095 internal_props->accel_type =
1096 hw_accel_from_pixfmt(s->codec_ctx->pix_fmt);
1097 return DECODER_GOT_CODEC;
1098 }
1099
1100 return DECODER_GOT_FRAME;
1101}
1102
1103ADD_TO_PARAM("lavd-accept-corrupted",
1104 "* lavd-accept-corrupted[=no]\n"
1105 " Pass corrupted frames to decoder. If decoder isn't error-resilient,\n"
1106 " may crash! Use \"no\" to disable even if enabled by default.\n");
1107static int libavcodec_decompress_get_property(void *state, int property, void *val, size_t *len)
1108{
1109 struct state_libavcodec_decompress *s =
1111 int ret = false;
1112
1113 switch(property) {
1115 if (*len < sizeof(int)) {
1116 return false;
1117 }
1118 *(int *) val = false;
1119 if (s->codec_ctx && strcmp(s->codec_ctx->codec->name, "h264") == 0) {
1120 *(int *) val = true;
1121 }
1122 if (get_commandline_param("lavd-accept-corrupted")) {
1123 *(int *) val =
1124 strcmp(get_commandline_param("lavd-accept-corrupted"), "no") != 0;
1125 }
1126
1127 *len = sizeof(int);
1128 ret = true;
1129 break;
1130 }
1131
1132 return ret;
1133}
1134
1136{
1137 struct state_libavcodec_decompress *s =
1139
1140 deconfigure(s);
1141
1142 free(s);
1143}
1144
1149static int libavcodec_decompress_get_priority(codec_t compression, struct pixfmt_desc internal, codec_t ugc) {
1150 if (internal.accel_type != HWACCEL_NONE &&
1151 hw_accel_to_ug_pixfmt(internal.accel_type) == ugc) {
1152 return VDEC_PRIO_PREFERRED;
1153 }
1154
1155 unsigned i = 0;
1156 for ( ; i < sizeof decoders / sizeof decoders[0]; ++i) {
1157 if (decoders[i].ug_codec == compression) {
1158 const AVCodec *const decoder =
1159 avcodec_find_decoder(decoders[i].avcodec_id);
1160 if (decoder != NULL) {
1161 break;
1162 }
1163 MSG(WARNING,
1164 "Codec %s supported by lavd but "
1165 "not compiled in FFmpeg build.\n",
1166 get_codec_name(compression));
1167 }
1168 }
1169 if (i == sizeof decoders / sizeof decoders[0]) { // lavd doesn't handle this compression
1170 return VDEC_PRIO_NA;
1171 }
1172
1173 switch (ugc) {
1174 case VIDEO_CODEC_NONE:
1175 return VDEC_PRIO_PROBE_LO; // for probe
1176 case UYVY:
1177 case RG48:
1178 case RGB:
1179 case RGBA:
1180 case R10k:
1181 case R12L:
1182 case v210:
1183 case Y416:
1184 break;
1185 default:
1186 return VDEC_PRIO_NA;
1187 }
1188 if (internal.depth == 0) { // unspecified internal format
1189 return VDEC_PRIO_LOW;
1190 }
1191 return codec_is_a_rgb(ugc) == internal.rgb ? VDEC_PRIO_NORMAL
1193}
1194
1203
1205
convert_t convert
#define UNUSED(x)
void ** state
int void * val
struct video_desc desc
struct video_frame * frame
const char * fmt
int void size_t * len
int property
int vc_get_linesize(unsigned int width, codec_t codec)
const char * get_codec_name(codec_t codec)
#define MOD_NAME
Definition libavcodec.c:70
static audio_channel * libavcodec_decompress(void *, audio_channel *)
Definition libavcodec.c:666
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define debug_file_dump(key, serialize, data)
Definition debug.h:86
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
av_to_uv_convert_t * get_av_to_uv_conversion(int av_codec, codec_t uv_codec)
enum AVPixelFormat lavd_get_av_to_ug_codec(const enum AVPixelFormat *fmt, codec_t c, bool use_hwaccel)
codec_t get_best_ug_codec_to_av(const enum AVPixelFormat *fmt, bool use_hwaccel)
void av_to_uv_conversion_destroy(av_to_uv_convert_t **s)
enum AVPixelFormat pick_av_convertible_to_ug(codec_t color_spec, av_to_uv_convert_t **av_conv)
void av_to_uv_convert(const av_to_uv_convert_t *convert, char *dst, AVFrame *in, int width, int height, int pitch, const int rgb_shift[3])
decompress_status
#define DECOMPRESS_PROPERTY_ACCEPTS_CORRUPTED_FRAME
@ DECODER_GOT_CODEC
Internal pixel format was determined.
@ DECODER_NO_FRAME
@ DECODER_UNSUPP_PIXFMT
Decoder can't decode to selected out_codec.
@ DECODER_GOT_FRAME
@ VDEC_PRIO_PREFERRED
@ VDEC_PRIO_NA
decoder cannot handle the codec in any way
@ VDEC_PRIO_LOW
@ VDEC_PRIO_NOT_PREFERRED
@ VDEC_PRIO_PROBE_LO
@ VDEC_PRIO_NORMAL
void exit_uv(int status)
Definition host.cpp:625
const char * get_commandline_param(const char *key)
Definition host.cpp:894
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
#define ADD_TO_PARAM(param, doc)
Definition host.h:203
enum hw_accel_type hw_accel_from_pixfmt(enum AVPixelFormat pixfmt)
void hwaccel_state_init(struct hw_accel_state *hwaccel)
Initializes hw_accel_state structure.
enum hw_accel_type hw_accel_from_str(const char *str)
void hwaccel_state_reset(struct hw_accel_state *hwaccel)
Uninitializes existing acceleration and resets hw_accel_state to initial state.
codec_t hw_accel_to_ug_pixfmt(enum hw_accel_type type)
This file contains functions related to hw acceleration.
int vaapi_init(struct AVCodecContext *s, struct hw_accel_state *state, codec_t out_codec)
This file contains functions related to hw acceleration.
int vdpau_init(struct AVCodecContext *s, struct hw_accel_state *state, codec_t out_codec)
This file contains functions related to hw acceleration.
int videotoolbox_init(struct AVCodecContext *s, struct hw_accel_state *state, codec_t out_codec)
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
const char * lavc_thread_type_to_str(int thread_type)
void print_decoder_error(const char *mod_name, int rc)
struct pixfmt_desc av_pixfmt_get_desc(enum AVPixelFormat pixfmt)
void lavd_flush(AVCodecContext *codec_ctx)
const char * get_avpixfmts_names(const enum AVPixelFormat *pixfmts)
void ug_set_av_logging()
Sets specified log level either given explicitly or from UG-wide log_level.
int av_pixfmt_get_subsampling(enum AVPixelFormat fmt)
void printf_libav_error(int verbosity, int rc, const char *msg,...)
bool libav_codec_has_extradata(codec_t codec)
#define AV_CODEC_CAP_OTHER_THREADS
Definition lavc_common.h:95
@ B_SHIFT_IDX
Definition lavc_common.h:69
@ G_SHIFT_IDX
Definition lavc_common.h:68
@ R_SHIFT_IDX
Definition lavc_common.h:67
#define AV_PIX_FMT_VULKAN
void serialize_video_avframe(const void *f, FILE *out)
Definition lavc_video.c:103
@ LIBRARY_CLASS_VIDEO_DECOMPRESS
Definition lib_common.h:81
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
#define SWAP_PTR(a, b)
Definition macros.h:58
static const struct decoder_item decoders[]
@ NAL_H264_SPS
Definition rtpdec_h264.h:62
@ NAL_HEVC_VPS
Definition rtpdec_h264.h:66
#define NALU_HDR_GET_TYPE(nal, is_hevc)
Definition rtpdec_h264.h:88
const char * get_nalu_name(int type)
const unsigned char * rtpenc_get_first_nal(const unsigned char *src, long src_len, bool hevc)
#define H264_NAL_SEI_PREFIX
Definition rtpenc_h264.h:52
#define UG_ORIG_FORMAT_ISO_IEC_11578_GUID
custom orig format byte syntax - highest 1 bit zero, next 2 bits (depth-8)/2, next 3 bits subsampling...
Definition rtpenc_h264.h:55
#define START_CODE_3B
Definition rtpenc_h264.h:50
#define HEVC_NAL_SEI_PREFIX
Definition rtpenc_h264.h:53
const char * param
Definition settings.cpp:195
codec_t ug_codec
Definition libavcodec.c:222
void(* codec_callback)(void)
Definition libavcodec.c:224
enum AVCodecID avcodec_id
Definition libavcodec.c:223
const char * preferred_decoders[MAX_PREFERED+1]
Definition libavcodec.c:234
enum hw_accel_type type
bool copy
Specifies whether to use the copy mode.
Definition hd-rum.c:27
int depth
bit depth; 0 means that whole struct is undefined
Definition types.h:140
enum hw_accel_type accel_type
Definition types.h:143
bool rgb
Definition types.h:142
int subsampling
in 'JabA' format, eg. '4444'
Definition types.h:141
struct state_libavcodec_decompress::state_libavcodec_decompress_sws sws
struct video_desc desc
Definition libavcodec.c:78
long long consecutive_failed_decodes
Definition libavcodec.c:88
enum AVPixelFormat convert_in
Definition libavcodec.c:85
_Bool sps_vps_found
to avoid initial error flood, start decoding after SPS (H.264) or VPS (HEVC) was received
Definition libavcodec.c:99
struct hw_accel_state hwaccel
Definition libavcodec.c:97
av_to_uv_convert_t * convert
Definition libavcodec.c:84
bool block_accel[HWACCEL_COUNT]
Definition libavcodec.c:87
AVCodecContext * codec_ctx
Definition libavcodec.c:73
codec_t color_spec
Definition types.h:182
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
Struct containing callbacks of a video_frame.
Definition types.h:230
long long time_ns_t
Definition tv.h:81
#define MS_IN_SEC
Definition tv.h:87
#define NS_IN_SEC
Definition tv.h:92
#define NS_IN_SEC_DBL
Definition tv.h:93
static time_ns_t get_time_in_ns()
Definition tv.h:101
#define NS_TO_MS(val_ns)
Definition tv.h:98
hw_accel_type
Definition types.h:114
@ HWACCEL_NONE
Definition types.h:115
@ HWACCEL_VULKAN
Definition types.h:120
@ HWACCEL_COUNT
Definition types.h:122
@ HWACCEL_CUDA
Definition types.h:119
@ HWACCEL_DRM_PRIME
Definition types.h:121
depth
Definition types.h:125
@ SUBS_420
Definition types.h:133
codec_t
Definition types.h:65
@ VP8
VP8 frame.
Definition types.h:86
@ PRORES_422_LT
Apple ProRes 422 (LT)
Definition types.h:106
@ R10k
RGB 10-bit packed - RGBX, big-endian (2 bit padding)
Definition types.h:73
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
@ PRORES
abstract Apple ProRes, must not be used in transmit
Definition types.h:100
@ PRORES_422_PROXY
Apple ProRes 422 (Proxy)
Definition types.h:105
@ HW_VDPAU
VDPAU hardware surface.
Definition types.h:91
@ RG48
16-bit RGB little-endian (RlRhGl...)
Definition types.h:95
@ AV1
AOMedia Video 1.
Definition types.h:96
@ Y416
interleaved little-endian YCbCr 4444 16-bit - UYVA
Definition types.h:99
@ J2KR
JPEG 2000 RGB.
Definition types.h:90
@ CFHD
Cineform.
Definition types.h:94
@ J2K
JPEG 2000.
Definition types.h:89
@ PRORES_422_HQ
Apple ProRes 422 (HQ)
Definition types.h:103
@ PRORES_4444
Apple ProRes 4444.
Definition types.h:101
@ JPEG
JPEG image, restart intervals may be used. Compatible with GPUJPEG.
Definition types.h:81
@ HFYU
HuffYUV.
Definition types.h:92
@ MJPG
JPEG image, without restart intervals.
Definition types.h:85
@ R12L
RGB 12-bit packed, little-endian.
Definition types.h:74
@ FFV1
FFV1.
Definition types.h:93
@ PRORES_422
Apple ProRes 422.
Definition types.h:104
@ DRM_PRIME
DRM Prime buffer, data contains struct drm_prime_frame.
Definition types.h:107
@ H264
H.264 frame.
Definition types.h:83
@ VP9
VP9 frame.
Definition types.h:87
@ H265
H.264 frame.
Definition types.h:84
@ PRORES_4444_XQ
Apple ProRes 4444 (XQ)
Definition types.h:102
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
Definition types.h:75
enum AVPixelFormat get_ug_to_av_pixfmt(codec_t ug_codec)
Definition utils.c:84
codec_t get_av_to_ug_pixfmt(enum AVPixelFormat av_pixfmt)
Definition utils.c:75
codec_t ug_codec
Definition v4l2_common.h:68
This is an umbrella header for video functions.
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).
uint32_t get_fourcc(codec_t codec)
bool codec_is_planar(codec_t codec)
const char * key
Definition cineform.cpp:125
static void deconfigure(struct state_libavcodec_decompress *s)
Definition libavcodec.c:108
static int libavcodec_decompress_reconfigure(void *state, struct video_desc desc, int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
Definition libavcodec.c:464
#define SELECT_PIXFMT(pixfmt)
static void libavcodec_decompress_done(void *state)
static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
Definition libavcodec.c:596
static void change_pixfmt(AVFrame *frame, unsigned char *dst, av_to_uv_convert_t *convert, codec_t out_codec, int width, int height, int pitch, int rgb_shift[static restrict 3], struct state_libavcodec_decompress_sws *sws)
Definition libavcodec.c:823
static _Bool check_first_sps_vps(struct state_libavcodec_decompress *s, unsigned char *src, unsigned int src_len)
Definition libavcodec.c:860
@ MAX_PREFERED
Definition libavcodec.c:216
@ DEC_LEN
Definition libavcodec.c:218
@ MAX_DECODERS
Definition libavcodec.c:217
static bool read_forced_pixfmt(codec_t compress, const unsigned char *src, unsigned int src_len, struct pixfmt_desc *internal_props)
Definition libavcodec.c:976
static int libavcodec_decompress_get_property(void *state, int property, void *val, size_t *len)
static bool get_usable_decoders(enum AVCodecID avcodec_id, const char *const preferred_decoders[static MAX_PREFERED+1], const AVCodec *usable_decoders[static DEC_LEN])
Definition libavcodec.c:259
static void check_duration(struct state_libavcodec_decompress *s, double duration_total_sec, double duration_pixfmt_change_sec)
print hint to improve performance if not making it
Definition libavcodec.c:898
static int drm_prime_init(struct AVCodecContext *s, struct hw_accel_state *state, codec_t out_codec)
Definition libavcodec.c:490
static void * libavcodec_decompress_init(void)
Definition libavcodec.c:442
static _Bool reconfigure_convert_if_needed(struct state_libavcodec_decompress *s, enum AVPixelFormat av_codec, codec_t out_codec, int width, int height)
Definition libavcodec.c:772
static bool decode_frame(struct state_libavcodec_decompress *s, unsigned char *src, int src_len)
static void set_codec_context_params(struct state_libavcodec_decompress *s)
Definition libavcodec.c:145
static bool validate_hwacc_param(void)
Definition libavcodec.c:418
static int check_av_opt_set(void *state, const char *key, const char *val)
Definition libavcodec.c:134
static void jpeg_callback(void)
Definition libavcodec.c:209
static const struct video_decompress_info libavcodec_info
static void handle_lavd_error(const char *prefix, struct state_libavcodec_decompress *s, int ret)
Definition libavcodec.c:954
static int libavcodec_decompress_get_priority(codec_t compression, struct pixfmt_desc internal, codec_t ugc)
static bool configure_with(struct state_libavcodec_decompress *s, struct video_desc desc, void *extradata, int extradata_size)
Definition libavcodec.c:336
API for video decompress drivers.
#define VIDEO_DECOMPRESS_ABI_VERSION
void buf_get_linesizes(int width, codec_t color_spec, int *linesize)
void buf_get_planes(int width, int height, codec_t color_spec, char *data, char **planes)