FFmpegfs Fuse Multi Media Filesystem 2.16
ffmpeg_transcoder.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2024 Norbert Schlia (nschlia@oblivion-software.de)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * On Debian systems, the complete text of the GNU General Public License
19 * Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
20 */
21
32#ifdef __cplusplus
33extern "C" {
34#endif
35// Disable annoying warnings outside our code
36#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wconversion"
38#pragma GCC diagnostic ignored "-Wsign-conversion"
39#include <libswscale/swscale.h>
40#include <libavutil/imgutils.h>
41#include <libavutil/opt.h>
42#include <libavutil/audio_fifo.h>
43#include <libavfilter/avfilter.h>
44#include <libavfilter/buffersink.h>
45#include <libavfilter/buffersrc.h>
46#include <libavcodec/avcodec.h>
47#include <libavformat/avformat.h>
48#include <libavformat/avio.h>
49#include <libavutil/file.h>
50#include <libswresample/swresample.h>
51#pragma GCC diagnostic pop
52#ifdef __cplusplus
53}
54#endif
55
56#include "ffmpeg_transcoder.h"
57#include "buffer.h"
58#include "wave.h"
59#include "aiff.h"
60#include "logging.h"
61#include "ffmpegfs.h"
62
63#include <unistd.h>
64#include <filesystem>
65#include <thread>
66
67#define FRAME_SEEK_THRESHOLD 25
69const std::vector<FFmpeg_Transcoder::PRORES_BITRATE> FFmpeg_Transcoder::m_prores_bitrate =
70{
71 // SD
72 { 720, 486, { { 24, false } }, { 10, 23, 34, 50, 75, 113 } },
73 { 720, 486, { { 60, true }, { 30, false } }, { 12, 29, 42, 63, 94, 141 } },
74
75 { 720, 576, { { 50, true }, { 25, false } }, { 12, 28, 41, 61, 92, 138 } },
76
77 { 960, 720, { { 24, false } }, { 15, 35, 50, 75, 113, 170 } },
78 { 960, 720, { { 25, false } }, { 16, 36, 52, 79, 118, 177 } },
79 { 960, 720, { { 30, false } }, { 19, 44, 63, 94, 141, 212 } },
80 { 960, 720, { { 50, false } }, { 32, 73, 105, 157, 236, 354 } },
81 { 960, 720, { { 60, false } }, { 38, 87, 126, 189, 283, 424 } },
82 // HD
83 { 1280, 720, { { 24, false } }, { 18, 41, 59, 88, 132, 198 } },
84 { 1280, 720, { { 25, false } }, { 19, 42, 61, 92, 138, 206 } },
85 { 1280, 720, { { 30, false } }, { 23, 51, 73, 110, 165, 247 } },
86 { 1280, 720, { { 50, false } }, { 38, 84, 122, 184, 275, 413 } },
87 { 1280, 720, { { 60, false } }, { 45, 101, 147, 220, 330, 495 } },
88
89 { 1280, 1080, { { 24, false } }, { 31, 70, 101, 151, 226, 339 } },
90 { 1280, 1080, { { 60, true }, { 30, false } }, { 38, 87, 126, 189, 283, 424 } },
91
92 { 1440, 1080, { { 24, false } }, { 31, 70, 101, 151, 226, 339 } },
93 { 1440, 1080, { { 50, true }, { 25, false } }, { 32, 73, 105, 157, 236, 354 } },
94 { 1440, 1080, { { 60, true }, { 30, false } }, { 38, 87, 126, 189, 283, 424 } },
95 // Full HD
96 { 1920, 1080, { { 24, false } }, { 36, 82, 117, 176, 264, 396 } },
97 { 1920, 1080, { { 50, true }, { 25, false } }, { 38, 85, 122, 184, 275, 413 } },
98 { 1920, 1080, { { 60, true }, { 30, false } }, { 45, 102, 147, 220, 330, 495 } },
99 { 1920, 1080, { { 50, false } }, { 76, 170, 245, 367, 551, 826 } },
100 { 1920, 1080, { { 60, false } }, { 91, 204, 293, 440, 660, 990 } },
101 // 2K
102 { 2048, 1080, { { 24, false } }, { 41, 93, 134, 201, 302, 453 } },
103 { 2048, 1080, { { 25, false } }, { 43, 97, 140, 210, 315, 472 } },
104 { 2048, 1080, { { 30, false } }, { 52, 116, 168, 251, 377, 566 } },
105 { 2048, 1080, { { 50, false } }, { 86, 194, 280, 419, 629, 944 } },
106 { 2048, 1080, { { 60, false } }, { 103, 232, 335, 503, 754, 1131 } },
107 // 2K
108 { 2048, 1556, { { 24, false } }, { 56, 126, 181, 272, 407, 611 } },
109 { 2048, 1556, { { 25, false } }, { 58, 131, 189, 283, 425, 637 } },
110 { 2048, 1556, { { 30, false } }, { 70, 157, 226, 340, 509, 764 } },
111 { 2048, 1556, { { 50, false } }, { 117, 262, 377, 567, 850, 1275 } },
112 { 2048, 1556, { { 60, false } }, { 140, 314, 452, 679, 1019, 1528 } },
113 // QFHD
114 { 3840, 2160, { { 24, false } }, { 145, 328, 471, 707, 1061, 1591 } },
115 { 3840, 2160, { { 25, false } }, { 151, 342, 492, 737, 1106, 1659 } },
116 { 3840, 2160, { { 30, false } }, { 182, 410, 589, 884, 1326, 1989 } },
117 { 3840, 2160, { { 50, false } }, { 303, 684, 983, 1475, 2212, 3318 } },
118 { 3840, 2160, { { 60, false } }, { 363, 821, 1178, 1768, 2652, 3977 } },
119 // 4K
120 { 4096, 2160, { { 24, false } }, { 155, 350, 503, 754, 1131, 1697 } },
121 { 4096, 2160, { { 25, false } }, { 162, 365, 524, 786, 1180, 1769 } },
122 { 4096, 2160, { { 30, false } }, { 194, 437, 629, 943, 1414, 2121 } },
123 { 4096, 2160, { { 50, false } }, { 323, 730, 1049, 1573, 2359, 3539 } },
124 { 4096, 2160, { { 60, false } }, { 388, 875, 1257, 1886, 2828, 4242 } },
125 // 5K
126 { 5120, 2700, { { 24, false } }, { 243, 547, 786, 1178, 1768, 2652 } },
127 { 5120, 2700, { { 25, false } }, { 253, 570, 819, 1229, 1843, 2765 } },
128 { 5120, 2700, { { 30, false } }, { 304, 684, 982, 1473, 2210, 3314 } },
129 { 5120, 2700, { { 50, false } }, { 507, 1140, 1638, 2458, 3686, 5530 } },
130 { 5120, 2700, { { 60, false } }, { 608, 1367, 1964, 2946, 4419, 6629 } },
131 // 6K
132 { 6144, 3240, { { 24, false } }, { 350, 788, 1131, 1697, 2545, 3818 } },
133 { 6144, 3240, { { 25, false } }, { 365, 821, 1180, 1769, 2654, 3981 } },
134 { 6144, 3240, { { 30, false } }, { 437, 985, 1414, 2121, 3182, 4772 } },
135 { 6144, 3240, { { 50, false } }, { 730, 1643, 2359, 3539, 5308, 7962 } },
136 { 6144, 3240, { { 60, false } }, { 875, 1969, 2828, 4242, 6364, 9545 } },
137 // 8K
138 { 8192, 4320, { { 24, false } }, { 622, 1400, 2011, 3017, 4525, 6788 } },
139 { 8192, 4320, { { 25, false } }, { 649, 1460, 2097, 3146, 4719, 7078 } },
140 { 8192, 4320, { { 30, false } }, { 778, 1750, 2514, 3771, 5657, 8485 } },
141 { 8192, 4320, { { 50, false } }, { 1298, 2920, 4194, 6291, 9437, 14156 } },
142 { 8192, 4320, { { 60, false } }, { 1556, 3500, 5028, 7542, 11313, 16970 } }
143};
144
146{
147 { AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_NV12 },
148 #if 0
149 { AV_HWDEVICE_TYPE_CUDA, AV_PIX_FMT_CUDA },
150 { AV_HWDEVICE_TYPE_VDPAU, AV_PIX_FMT_YUV420P },
151 { AV_HWDEVICE_TYPE_QSV, AV_PIX_FMT_QSV },
152 { AV_HWDEVICE_TYPE_OPENCL, AV_PIX_FMT_OPENCL },
153 #if HAVE_VULKAN_HWACCEL
154 { AV_HWDEVICE_TYPE_VULKAN, AV_PIX_FMT_VULKAN },
155 #endif // HAVE_VULKAN_HWACCEL
156 #if __APPLE__
157 { AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX },
158 #endif // __APPLE__
159 #if __ANDROID__
160 { AV_HWDEVICE_TYPE_MEDIACODEC, AV_PIX_FMT_MEDIACODEC },
161 #endif // __ANDROID__
162 #if _WIN32
163 { AV_HWDEVICE_TYPE_DRM, AV_PIX_FMT_DRM_PRIME },
164 { AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD },
165 { AV_HWDEVICE_TYPE_D3D11VA, AV_PIX_FMT_D3D11VA_VLD },
166 #endif // _WIN32
167 #endif
168};
169
170FFmpeg_Transcoder::StreamRef::StreamRef() :
171 m_codec_ctx(nullptr),
172 m_stream(nullptr),
173 m_stream_idx(INVALID_STREAM),
174 m_start_time(0)
175{
176
177}
178FFmpeg_Transcoder::StreamRef::~StreamRef()
179{
180 reset();
181}
182
183template< typename T >
185{
190 void operator ()( T * p) const
191 {
192 avcodec_free_context(&p);
193 }
194};
195
196void FFmpeg_Transcoder::StreamRef::set_codec_ctx(AVCodecContext *codec_ctx)
197{
198 if (codec_ctx != nullptr)
199 {
200 std::shared_ptr<AVCodecContext> sp(codec_ctx, av_context_deleter<AVCodecContext>());
201
202 m_codec_ctx = sp;
203 }
204 else
205 {
206 m_codec_ctx.reset();
207 }
208}
209
211{
212 m_codec_ctx.reset();
213}
214
215#pragma GCC diagnostic push
216#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
218 : m_fileio(nullptr)
220 , m_have_seeked(false)
221 , m_skip_next_frame(false)
222 , m_is_video(false)
223 , m_cur_sample_fmt(AV_SAMPLE_FMT_NONE)
225 , m_audio_resample_ctx(nullptr)
226 , m_audio_fifo(nullptr)
227 , m_sws_ctx(nullptr)
228 , m_buffer_sink_context(nullptr)
229 , m_buffer_source_context(nullptr)
230 , m_filter_graph(nullptr)
231 , m_pts(AV_NOPTS_VALUE)
232 , m_pos(AV_NOPTS_VALUE)
234 , m_insert_keyframe(true)
235 , m_copy_audio(false)
236 , m_copy_video(false)
237 , m_cur_audio_ts(0)
238 , m_cur_video_ts(0)
239 , m_current_format(nullptr)
240 , m_buffer(nullptr)
241 , m_reset_pts(0)
242 , m_fake_frame_no(0)
247 , m_hwaccel_enc_device_ctx(nullptr)
248 , m_hwaccel_dec_device_ctx(nullptr)
249 , m_enc_hw_pix_fmt(AV_PIX_FMT_NONE)
250 , m_dec_hw_pix_fmt(AV_PIX_FMT_NONE)
253{
254#pragma GCC diagnostic pop
255 Logging::trace(nullptr, "The FFmpeg trancoder is ready to initialise.");
256
257 std::memset(&m_mtime, 0, sizeof(m_mtime));
258
259#if LAVU_DEP_OLD_CHANNEL_LAYOUT
260 av_channel_layout_default(&m_cur_ch_layout, params.m_audiochannels);
261#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
262 m_cur_channel_layout = static_cast<uint64_t>(av_get_default_channel_layout(params.m_audiochannels));
263#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
264
265 // Initialise ID3v1.1 tag structure
267}
268
270{
271 // Close files and resample context
272 closeio();
273
274 Logging::trace(nullptr, "The FFmpeg transcoder object was destroyed.");
275}
276
278{
279 bool is_video = false;
280
281 if (m_in.m_video.m_codec_ctx != nullptr && m_in.m_video.m_stream != nullptr)
282 {
283 is_video = !is_album_art(m_in.m_video.m_codec_ctx->codec_id, &m_in.m_video.m_stream->r_frame_rate);
284 }
285
286 return is_video;
287}
288
290{
291 return (m_in.m_format_ctx != nullptr);
292}
293
294int FFmpeg_Transcoder::open_input_file(LPVIRTUALFILE virtualfile, std::shared_ptr<FileIO> fio)
295{
296 AVDictionary * opt = nullptr;
297 int ret;
298
299 if (virtualfile == nullptr)
300 {
301 Logging::error(filename(), "INTERNAL ERROR: FFmpeg_Transcoder::open_input_file()! virtualfile is NULL.");
302 return AVERROR(EINVAL);
303 }
304
305 m_virtualfile = virtualfile;
306
307 m_mtime = m_virtualfile->m_st.st_mtime;
309
310 if (is_open())
311 {
312 Logging::warning(filename(), "The file is already open.");
313 return 0;
314 }
315
316 // This allows selecting if the demuxer should consider all streams to be
317 // found after the first PMT and add further streams during decoding or if it rather
318 // should scan all that are within the analyze-duration and other limits
319 ret = dict_set_with_check(&opt, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
320 if (ret < 0)
321 {
322 return ret;
323 }
324
325 // avioflags direct: Reduce buffering.
326 //ret = dict_set_with_check(&opt, "avioflags", "direct", AV_DICT_DONT_OVERWRITE);
327 //if (ret < 0)
328 //{
329 // return ret;
330 //}
331
332 // analyzeduration: Defaults to 5,000,000 microseconds = 5 seconds.
333 ret = dict_set_with_check(&opt, "analyzeduration", "15000000", 0); // <<== honored: 15 seconds
334 if (ret < 0)
335 {
336 return ret;
337 }
338
339 // probesize: 5000000 by default.
340 ret = dict_set_with_check(&opt, "probesize", "15000000", 0); // <<== honoured: ~15 MB
341 if (ret < 0)
342 {
343 return ret;
344 }
345
346 // using own I/O
347 if (fio == nullptr)
348 {
349 // Open new file io
351 }
352 else
353 {
354 // Use already open file io
355 m_fileio = fio;
356 }
357
358 if (m_fileio == nullptr)
359 {
360 int orgerrno = errno;
361 Logging::error(filename(), "Error opening file: (%1) %2", errno, strerror(errno));
362 return AVERROR(orgerrno);
363 }
364
365 ret = m_fileio->openio(m_virtualfile);
366 if (ret)
367 {
368 return AVERROR(ret);
369 }
370
371 m_in.m_format_ctx = avformat_alloc_context();
372 if (m_in.m_format_ctx == nullptr)
373 {
374 Logging::error(filename(), "Out of memory opening file: format context could not be allocated.");
375 return AVERROR(ENOMEM);
376 }
377
378 unsigned char *iobuffer = static_cast<unsigned char *>(av_malloc(m_fileio->bufsize() + FF_INPUT_BUFFER_PADDING_SIZE));
379 if (iobuffer == nullptr)
380 {
381 Logging::error(filename(), "Out of memory opening file: I/O buffer could not be allocated.");
382 avformat_free_context(m_in.m_format_ctx);
383 m_in.m_format_ctx = nullptr;
384 return AVERROR(ENOMEM);
385 }
386
387 AVIOContext * pb = avio_alloc_context(
388 iobuffer,
389 static_cast<int>(m_fileio->bufsize()),
390 0,
391 static_cast<void *>(m_fileio.get()),
393 nullptr, // input_write
394 seek); // input_seek
395 m_in.m_format_ctx->pb = pb;
396
397#if IF_DECLARED_CONST
398 const AVInputFormat * infmt = nullptr;
399#else // !IF_DECLARED_CONST
400 AVInputFormat * infmt = nullptr;
401#endif // !IF_DECLARED_CONST
402
403#ifdef USE_LIBVCD
405 {
406 Logging::debug(filename(), "To avoid misdetection, forcing MPEG format for VCD source.");
407 infmt = av_find_input_format("mpeg");
408 }
409#endif // USE_LIBVCD
410#ifdef USE_LIBDVD
412 {
413 Logging::debug(filename(), "To avoid misdetection, forcing MPEG format for DVD source.");
414 infmt = av_find_input_format("mpeg");
415 }
416#endif // USE_LIBDVD
417#ifdef USE_LIBBLURAY
419 {
420 Logging::debug(filename(), "To avoid misdetection, forcing MPEGTS format for Blu-ray source.");
421 infmt = av_find_input_format("mpegts");
422 }
423#endif // USE_LIBBLURAY
424
447 // Open the input file to read from it.
448 ret = avformat_open_input(&m_in.m_format_ctx, filename(), infmt, &opt);
449 if (ret < 0)
450 {
451 Logging::error(filename(), "Could not open input file (error '%1').", ffmpeg_geterror(ret).c_str());
452 return ret;
453 }
454
456
457#if HAVE_AV_FORMAT_INJECT_GLOBAL_SIDE_DATA
458 av_format_inject_global_side_data(m_in.m_format_ctx);
459#endif
460
461 // Get information on the input file (number of streams etc.).
462 ret = avformat_find_stream_info(m_in.m_format_ctx, nullptr);
463 if (ret < 0)
464 {
465 Logging::error(filename(), "Could not find stream info (error '%1').", ffmpeg_geterror(ret).c_str());
466 return ret;
467 }
468
469#ifdef USE_LIBDVD
471 {
472 // FFmpeg API calculates a wrong duration, so use value from IFO
473 m_in.m_format_ctx->duration = m_fileio->duration();
474 }
475#endif // USE_LIBDVD
476#ifdef USE_LIBBLURAY
478 {
479 // FFmpeg API calculates a wrong duration, so use value from Blu-ray directory
480 m_in.m_format_ctx->duration = m_fileio->duration();
481 }
482#endif // USE_LIBBLURAY
483
485
486 ret = open_bestmatch_video();
487 if (ret < 0)
488 {
489 // Already logged
490 return ret;
491 }
492
493#ifdef USE_LIBDVD
495 {
496 // FFmpeg API sometimes cannot detect video size or frame rate, so use value from IFO
497 if (!m_in.m_video.m_codec_ctx->width || !m_in.m_video.m_stream->codecpar->height)
498 {
499 m_in.m_video.m_codec_ctx->width = m_in.m_video.m_stream->codecpar->width = m_virtualfile->m_width;
500 m_in.m_video.m_codec_ctx->height = m_in.m_video.m_stream->codecpar->height = m_virtualfile->m_height;
501 }
502 if (!m_in.m_video.m_stream->avg_frame_rate.den)
503 {
504 m_in.m_video.m_stream->avg_frame_rate = m_virtualfile->m_framerate;
505 }
506 }
507#endif // USE_LIBDVD
508#ifdef USE_LIBBLURAY
510 {
511 // FFmpeg API sometimes cannot detect video size or frame rate, so use value from Blu-ray directory
512 if (!m_in.m_video.m_codec_ctx->width || !m_in.m_video.m_stream->codecpar->height)
513 {
514 m_in.m_video.m_codec_ctx->width = m_in.m_video.m_stream->codecpar->width = m_virtualfile->m_width;
515 m_in.m_video.m_codec_ctx->height = m_in.m_video.m_stream->codecpar->height = m_virtualfile->m_height;
516 }
517 if (!m_in.m_video.m_stream->avg_frame_rate.den)
518 {
519 m_in.m_video.m_stream->avg_frame_rate = m_virtualfile->m_framerate;
520 }
521 }
522#endif // USE_LIBBLURAY
523
524 ret = open_bestmatch_audio();
525 if (ret < 0)
526 {
527 // Already logged
528 return ret;
529 }
530
532 {
533 Logging::error(filename(), "The file contains neither a video nor an audio stream.");
534 return AVERROR(EINVAL);
535 }
536
538 {
539 ret = open_subtitles();
540 if (ret < 0)
541 {
542 // Already logged
543 return ret;
544 }
545 }
546
547 // Predict size of transcoded file as exact as possible
549
550 // Calculate number or video frames in file based on duration and frame rate
551 if (m_in.m_video.m_stream != nullptr && m_in.m_video.m_stream->avg_frame_rate.den)
552 {
553 // Number of frames: should be quite accurate
554 m_virtualfile->m_video_frame_count = static_cast<uint32_t>(ffmpeg_rescale_q(m_in.m_video.m_stream->duration, m_in.m_video.m_stream->time_base, av_inv_q(m_in.m_video.m_stream->avg_frame_rate)));
555 }
556
557 ret = open_albumarts();
558 if (ret < 0)
559 {
560 // Already logged
561 return ret;
562 }
563
565 {
566 // Position to start of cue sheet track
567 ret = av_seek_frame(m_in.m_format_ctx, -1, m_virtualfile->m_cuesheet_track.m_start, 0);
568 if (ret < 0)
569 {
570 Logging::error(filename(), "The track start was nout found (error '%1').", ffmpeg_geterror(ret).c_str());
571 return ret;
572 }
573 }
574
575 return 0;
576}
577
579{
580 // Issue #80: Open input video codec, but only if target supports video.
581 // Saves resources: no need to decode video frames if not used.
582 if (m_current_format->video_codec() != AV_CODEC_ID_NONE)
583 {
584 int ret;
585
586 // Open best match video codec
587 AVCodecContext * codec_ctx = nullptr;
588 ret = open_bestmatch_decoder(m_in.m_format_ctx, &codec_ctx, &m_in.m_video.m_stream_idx, AVMEDIA_TYPE_VIDEO);
589 if (ret < 0 && ret != AVERROR_STREAM_NOT_FOUND) // AVERROR_STREAM_NOT_FOUND is not an error
590 {
591 Logging::error(filename(), "The video codec could not be opened (error '%1').", ffmpeg_geterror(ret).c_str());
592 return ret;
593 }
594 m_in.m_video.set_codec_ctx(codec_ctx);
595
597 {
598 // We have a video stream
599 // Check to see if encoder hardware acceleration is both requested and supported by codec.
600 std::string hw_encoder_codec_name;
601 if (!get_hw_encoder_name(m_current_format->video_codec(), &hw_encoder_codec_name))
602 {
603 // API supports hardware frame buffers
605 }
606
608 {
609 // Hardware buffers available, enabling encoder hardware accceleration.
610 Logging::trace(virtname(), "Hardware encoder frame buffering %1 is enabled.", get_hwaccel_API_text(params.m_hwaccel_enc_API).c_str());
612 if (ret < 0)
613 {
614 Logging::error(virtname(), "Failed to create a %1 device for encoding (error %2).", get_hwaccel_API_text(params.m_hwaccel_enc_API).c_str(), ffmpeg_geterror(ret).c_str());
615 return ret;
616 }
617 Logging::info(virtname(), "Hardware encoder acceleration and frame buffering are active using codec '%1'.", hw_encoder_codec_name.c_str());
618 }
619 else if (params.m_hwaccel_enc_device_type != AV_HWDEVICE_TYPE_NONE)
620 {
621 // No hardware acceleration, fallback to software,
622 Logging::debug(virtname(), "Hardware encoder frame buffering %1 is not supported by codec '%2'. Falling back to software.", get_hwaccel_API_text(params.m_hwaccel_enc_API).c_str(), get_codec_name(m_in.m_video.m_codec_ctx->codec_id, true));
623 }
624 else if (!hw_encoder_codec_name.empty())
625 {
626 // No frame buffering (e.g. OpenMAX or MMAL), but hardware acceleration possible.
627 Logging::info(virtname(), "Hardware encoder acceleration is active using codec '%1'.", hw_encoder_codec_name.c_str());
628 }
629
631
632#ifdef USE_LIBDVD
634 {
635 // FFmpeg API calculates a wrong duration, so use value from IFO
636 m_in.m_video.m_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), m_in.m_video.m_stream->time_base);
637 }
638#endif // USE_LIBDVD
639#ifdef USE_LIBBLURAY
641 {
642 // FFmpeg API calculates a wrong duration, so use value from Blu-ray
643 m_in.m_video.m_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), m_in.m_video.m_stream->time_base);
644 }
645#endif // USE_LIBBLURAY
646
648
650
651#if !LAVC_DEP_FLAG_TRUNCATED
652#ifdef AV_CODEC_CAP_TRUNCATED
653 if (m_in.m_video.m_codec_ctx->codec->capabilities & AV_CODEC_CAP_TRUNCATED)
654 {
655 m_in.m_video.m_codec_ctx->flags|= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
656 }
657#else
658#warning "Your FFMPEG distribution is missing AV_CODEC_CAP_TRUNCATED flag. Probably requires fixing!"
659#endif
660#endif // !LAVC_DEP_FLAG_TRUNCATED
661 }
662 }
663 return 0;
664}
665
667{
668 int ret;
669
670 // Open best match audio codec
671 AVCodecContext * codec_ctx = nullptr;
672 ret = open_bestmatch_decoder(m_in.m_format_ctx, &codec_ctx, &m_in.m_audio.m_stream_idx, AVMEDIA_TYPE_AUDIO);
673 if (ret < 0 && ret != AVERROR_STREAM_NOT_FOUND) // AVERROR_STREAM_NOT_FOUND is not an error
674 {
675 Logging::error(filename(), "The audio codec could not be opened (error '%1').", ffmpeg_geterror(ret).c_str());
676 return ret;
677 }
678 m_in.m_audio.set_codec_ctx(codec_ctx);
679
681 {
682 // We have an audio stream
684
685#ifdef USE_LIBDVD
687 {
688 // FFmpeg API calculates a wrong duration, so use value from IFO
689 m_in.m_audio.m_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), m_in.m_audio.m_stream->time_base);
690 }
691#endif // USE_LIBDVD
692#ifdef USE_LIBBLURAY
694 {
695 // FFmpeg API calculates a wrong duration, so use value from Blu-ray directory
696 m_in.m_audio.m_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), m_in.m_audio.m_stream->time_base);
697 }
698#endif // USE_LIBBLURAY
699
701 }
702 return 0;
703}
704
706{
707 // If target supports subtitles, check to transcode subtitles
708 for (int stream_idx = 0; stream_idx < static_cast<int>(m_in.m_format_ctx->nb_streams); stream_idx++)
709 {
710 AVStream * stream = m_in.m_format_ctx->streams[stream_idx];
711
712 if (avcodec_get_type(stream->codecpar->codec_id) != AVMEDIA_TYPE_SUBTITLE)
713 {
714 continue;
715 }
716
717 if (m_current_format->subtitle_codec(stream->codecpar->codec_id) == AV_CODEC_ID_NONE)
718 {
719 // No match, no support for this type of subtitle
720 continue;
721 }
722
723 AVCodecContext * codec_ctx = nullptr;
724 int ret;
725
726 ret = open_decoder(m_in.m_format_ctx, &codec_ctx, stream_idx, nullptr, AVMEDIA_TYPE_SUBTITLE);
727 if (ret < 0)
728 {
729 Logging::error(filename(), "The subtitle codec could not be opened (error '%1').", ffmpeg_geterror(ret).c_str());
730 return ret;
731 }
732
733 codec_ctx->pkt_timebase = codec_ctx->time_base = stream->time_base;
734
735 StreamRef input_streamref;
736
737 // We have a subtitle stream
738 input_streamref.set_codec_ctx(codec_ctx);
739 input_streamref.m_stream = stream;
740 input_streamref.m_stream_idx = stream_idx;
741
742 m_in.m_subtitle.insert(std::make_pair(input_streamref.m_stream_idx, input_streamref));
743
744 subtitle_info(false, m_in.m_format_ctx, input_streamref.m_stream);
745 }
746 return 0;
747}
748
750{
751 // Open album art streams if present and supported by both source and target
752 if (!params.m_noalbumarts && m_in.m_audio.m_stream != nullptr)
753 {
754 for (int stream_idx = 0; stream_idx < static_cast<int>(m_in.m_format_ctx->nb_streams); stream_idx++)
755 {
756 AVStream *input_stream = m_in.m_format_ctx->streams[stream_idx];
757
758 if (is_album_art(input_stream->codecpar->codec_id, &input_stream->r_frame_rate))
759 {
760 StreamRef streamref;
761 AVCodecContext * input_codec_ctx;
762 int ret;
763
764 Logging::trace(filename(), "Found album art.");
765
766 ret = open_decoder(m_in.m_format_ctx, &input_codec_ctx, stream_idx, nullptr, AVMEDIA_TYPE_VIDEO);
767 if (ret < 0)
768 {
769 Logging::error(filename(), "The album art codec could not be opened (error '%1').", ffmpeg_geterror(ret).c_str());
770 return ret;
771 }
772
773 streamref.set_codec_ctx(input_codec_ctx);
774 streamref.m_stream = input_stream;
775 streamref.m_stream_idx = input_stream->index;
776
777 m_in.m_album_art.push_back(streamref);
778 }
779 }
780 }
781 return 0;
782}
783
784bool FFmpeg_Transcoder::can_copy_stream(const AVStream *stream) const
785{
787 {
788 // Auto copy disabled
789 return false;
790 }
791
792 if (stream == nullptr)
793 {
794 // Should normally not happen: Input stream stream unknown, no way to check - no auto copy
795 return false;
796 }
797
798 AVMediaType codec_type = stream->codecpar->codec_type;
799 AVCodecID codec_in = stream->codecpar->codec_id;
800 std::string codec_type_str;
801 AVCodecID codec_out;
802 int64_t bitrate_out;
803 if (codec_type == AVMEDIA_TYPE_VIDEO)
804 {
805 codec_type_str = "video";
806 codec_out = m_current_format->video_codec();
807 bitrate_out = params.m_videobitrate;
808 }
809 else if (codec_type == AVMEDIA_TYPE_AUDIO)
810 {
811 codec_type_str = "audio";
812 codec_out = m_current_format->audio_codec();
813 bitrate_out = params.m_audiobitrate;
814 }
815 else
816 {
817 // Codec is not video or audio
818 return false;
819 }
820
822 {
823 // Any codec supported by output format OK
824 const AVOutputFormat* oformat = av_guess_format(nullptr, virtname(), nullptr);
825 if (oformat->codec_tag == nullptr || av_codec_get_tag(oformat->codec_tag, stream->codecpar->codec_id) <= 0)
826 {
827 // Codec not supported - no auto copy
828 return false;
829 }
830 }
832 {
833 // Output codec must strictly match
834 Logging::debug(virtname(), "Check autocopy strict: %1: %2 -> %3", codec_type_str.c_str(), avcodec_get_name(codec_in), avcodec_get_name(codec_out));
835 if (codec_in != codec_out)
836 {
837 // Different codecs - no auto copy
838 return false;
839 }
840 }
841
843 {
844 BITRATE orig_bit_rate = (stream->codecpar->bit_rate != 0) ? stream->codecpar->bit_rate : m_in.m_format_ctx->bit_rate;
845 if (get_output_bit_rate(orig_bit_rate, bitrate_out))
846 {
847 // Bit rate changed, no auto copy
848 Logging::info(virtname(), "Because the bit rate has changed, no auto copy is possible.");
849 return false;
850 }
851 }
852
853 return true;
854}
855
857{
858 if (buffer == nullptr)
859 {
860 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::open_output_file()! buffer == nullptr in open_output_file()");
861 return AVERROR(EINVAL);
862 }
863
865
866 Logging::debug(virtname(), "Opening the output file.");
867
868 if (!stream_exists(m_in.m_audio.m_stream_idx) && m_current_format->video_codec() == AV_CODEC_ID_NONE)
869 {
870 Logging::error(virtname(), "Unable to transcode. The source contains no audio stream, but the target just supports audio.");
871 m_virtualfile->m_flags |= VIRTUALFLAG_HIDDEN; // Hide file from now on
872 return AVERROR(ENOENT); // Report file not found
873 }
874
875 if (!is_frameset())
876 {
877 // Not a frame set, open regular buffer
878 return open_output(buffer);
879 }
880 else
881 {
882 Logging::debug(virtname(), "Opening frame set type '%1'.", m_current_format->desttype().c_str());
883
884 // Open frame set buffer
885 return open_output_frame_set(buffer);
886 }
887}
888
889int FFmpeg_Transcoder::open_bestmatch_decoder(AVFormatContext *format_ctx, AVCodecContext **codec_ctx, int *stream_idx, AVMediaType type)
890{
891#if IF_DECLARED_CONST
892 const AVCodec *input_codec = nullptr;
893#else // !IF_DECLARED_CONST
894 AVCodec *input_codec = nullptr;
895#endif // !IF_DECLARED_CONST
896 int ret;
897
898 *codec_ctx = nullptr;
899 *stream_idx = INVALID_STREAM;
900
901 ret = av_find_best_stream(format_ctx, type, INVALID_STREAM, INVALID_STREAM, &input_codec, 0);
902 if (ret < 0)
903 {
904 if (ret != AVERROR_STREAM_NOT_FOUND) // Not an error
905 {
906 Logging::error(filename(), "Could not find a %1 stream in the input file (error '%2').", get_media_type_string(type), ffmpeg_geterror(ret).c_str());
907 }
908 return ret;
909 }
910
911 *stream_idx = ret;
912
913 return open_decoder(format_ctx, codec_ctx, *stream_idx, input_codec, type);
914}
915
916#if IF_DECLARED_CONST
917AVPixelFormat FFmpeg_Transcoder::get_hw_pix_fmt(const AVCodec *codec, AVHWDeviceType dev_type, bool use_device_ctx) const
918#else // !IF_DECLARED_CONST
919AVPixelFormat FFmpeg_Transcoder::get_hw_pix_fmt(AVCodec *codec, AVHWDeviceType dev_type, bool use_device_ctx) const
920#endif // !IF_DECLARED_CONST
921{
922 AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE;
923
924 if (codec != nullptr && dev_type != AV_HWDEVICE_TYPE_NONE)
925 {
926 int method = use_device_ctx ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX;
927
928 for (int i = 0;; i++)
929 {
930 const AVCodecHWConfig *config = avcodec_get_hw_config(codec, i);
931 if (!config)
932 {
933 Logging::error(av_codec_is_decoder(codec) ? filename() : virtname(), "%1 '%2' does not support device type %3.\n", av_codec_is_encoder(codec) ? "Encoder" : "Decoder", codec->name, hwdevice_get_type_name(dev_type));
934 break;
935 }
936
937 if ((config->methods & method) && (config->device_type == dev_type))
938 {
939 hw_pix_fmt = config->pix_fmt;
940 Logging::debug(av_codec_is_decoder(codec) ? filename() : virtname(), "%1 '%2' requests %3 for device type %4.\n", av_codec_is_encoder(codec) ? "Encoder" : "Decoder", codec->name, av_get_pix_fmt_name(hw_pix_fmt), hwdevice_get_type_name(dev_type));
941 break;
942 }
943 }
944 }
945
946 return hw_pix_fmt;
947}
948
949#if IF_DECLARED_CONST
950int FFmpeg_Transcoder::open_decoder(AVFormatContext *format_ctx, AVCodecContext **codec_ctx, int stream_idx, const AVCodec *input_codec, AVMediaType mediatype)
951#else // !IF_DECLARED_CONST
952int FFmpeg_Transcoder::open_decoder(AVFormatContext *format_ctx, AVCodecContext **codec_ctx, int stream_idx, AVCodec *input_codec, AVMediaType mediatype)
953#endif // !IF_DECLARED_CONST
954{
955 while (true)
956 {
957 AVCodecContext *input_codec_ctx = nullptr;
958 AVStream * input_stream = nullptr;
959 AVDictionary * opt = nullptr;
960 AVCodecID codec_id = AV_CODEC_ID_NONE;
961 int ret;
962
963 input_stream = format_ctx->streams[stream_idx];
964
965 // Init the decoders, with or without reference counting
966 // av_dict_set_with_check(&opt, "refcounted_frames", refcount ? "1" : "0", 0);
967
968 // allocate a new decoding context
969 input_codec_ctx = avcodec_alloc_context3(nullptr);
970 if (input_codec_ctx == nullptr)
971 {
972 Logging::error(filename(), "Decoding context could not be allocated.");
973 return AVERROR(ENOMEM);
974 }
975
976 // initialise the stream parameters with demuxer information
977 ret = avcodec_parameters_to_context(input_codec_ctx, input_stream->codecpar);
978 if (ret < 0)
979 {
980 return ret;
981 }
982
983 codec_id = input_stream->codecpar->codec_id;
984
985 if (params.m_hwaccel_dec_API != HWACCELAPI::NONE)
986 {
987 if (mediatype == AVMEDIA_TYPE_VIDEO)
988 {
989 if (check_hwaccel_dec_blocked(input_stream->codecpar->codec_id, input_stream->codecpar->profile))
990 {
991 const char *profile = ::avcodec_profile_name(codec_id, input_stream->codecpar->profile);
992 Logging::info(filename(), "Codec '%1' profile '%2' is blocked from hardware decoding. Reverting to software decoder.", ::get_codec_name(codec_id), profile != nullptr ? profile : "unknown");
993 m_hwaccel_dec_mode = HWACCELMODE::FALLBACK;
994 }
995 }
996
997 if (mediatype == AVMEDIA_TYPE_VIDEO && m_hwaccel_dec_mode != HWACCELMODE::FALLBACK)
998 {
999 // Decide whether to use a hardware decoder
1000 // Check to see if decoder hardware acceleration is both requested and supported by codec.
1001 std::string hw_decoder_codec_name;
1002 if (!get_hw_decoder_name(input_codec_ctx->codec_id, &hw_decoder_codec_name))
1003 {
1004 m_dec_hw_pix_fmt = get_hw_pix_fmt(input_codec, params.m_hwaccel_dec_device_type, true);
1005
1006 m_hwaccel_enable_dec_buffering = (params.m_hwaccel_dec_device_type != AV_HWDEVICE_TYPE_NONE && m_dec_hw_pix_fmt != AV_PIX_FMT_NONE);
1007 //{
1008 // std::string fourcc2str;
1009 // fourcc_make_string(&fourcc2str, input_codec_ctx->codec_tag);
1010 // fprintf(stderr, "fourcc2str %s\n", fourcc2str.c_str());
1011 //}
1012 }
1013
1014 if (m_hwaccel_enable_dec_buffering)
1015 {
1016 // Hardware buffers available, enabling decoder hardware acceleration.
1017 Logging::trace(filename(), "Hardware decoder frame buffering %1 is enabled.", get_hwaccel_API_text(params.m_hwaccel_dec_API).c_str());
1018 ret = hwdevice_ctx_create(&m_hwaccel_dec_device_ctx, params.m_hwaccel_dec_device_type, params.m_hwaccel_dec_device);
1019 if (ret < 0)
1020 {
1021 Logging::error(filename(), "Failed to create a %1 device for decoding (error %2).", get_hwaccel_API_text(params.m_hwaccel_dec_API).c_str(), ffmpeg_geterror(ret).c_str());
1022 return ret;
1023 }
1024
1025 Logging::info(filename(), "Hardware decoder acceleration and frame buffering are active using codec '%1'.", (input_codec != nullptr) ? input_codec->name : "unknown");
1026
1027 m_hwaccel_dec_mode = HWACCELMODE::ENABLED; // Hardware acceleration active
1028 }
1029 else if (params.m_hwaccel_dec_device_type != AV_HWDEVICE_TYPE_NONE)
1030 {
1031 // No hardware acceleration, fallback to software,
1032 Logging::debug(filename(), "Hardware decoder frame buffering %1 not supported by codec '%2'. Falling back to software.", get_hwaccel_API_text(params.m_hwaccel_dec_API).c_str(), get_codec_name(input_codec_ctx->codec_id, true));
1033 }
1034 else if (!hw_decoder_codec_name.empty())
1035 {
1036 // No frame buffering (e.g. OpenMAX or MMAL), but hardware acceleration possible.
1037 // Open hw_decoder_codec_name codec here
1038 input_codec = avcodec_find_decoder_by_name(hw_decoder_codec_name.c_str());
1039
1040 if (input_codec == nullptr)
1041 {
1042 Logging::error(filename(), "Decoder '%1' could not be found.", hw_decoder_codec_name.c_str());
1043 return AVERROR(EINVAL);
1044 }
1045
1046 Logging::info(filename(), "Hardware decoder acceleration is active using codec '%1'.", input_codec->name);
1047
1048 m_hwaccel_dec_mode = HWACCELMODE::ENABLED; // Hardware acceleration active
1049 }
1050
1051 if (m_hwaccel_enable_dec_buffering)
1052 {
1053 ret = hwdevice_ctx_add_ref(input_codec_ctx);
1054 if (ret < 0)
1055 {
1056 return ret;
1057 }
1058 }
1059 }
1060 }
1061
1062 if (input_codec == nullptr)
1063 {
1064 // Find a decoder for the stream.
1065 input_codec = avcodec_find_decoder(codec_id);
1066
1067 if (input_codec == nullptr)
1068 {
1069 Logging::error(filename(), "Failed to find %1 input codec '%2'.", get_media_type_string(mediatype), avcodec_get_name(codec_id));
1070 return AVERROR(EINVAL);
1071 }
1072 }
1073
1074 input_codec_ctx->codec_id = input_codec->id;
1075
1076 //input_codec_ctx->time_base = input_stream->time_base;
1077
1078 ret = avcodec_open2(input_codec_ctx, input_codec, &opt);
1079
1080 av_dict_free(&opt);
1081
1082 if (ret < 0)
1083 {
1084 if (m_hwaccel_dec_mode == HWACCELMODE::ENABLED)
1085 {
1086 Logging::info(filename(), "Unable to use %1 input codec '%2' with hardware acceleration. Falling back to software.", get_media_type_string(mediatype), avcodec_get_name(codec_id));
1087
1088 m_hwaccel_dec_mode = HWACCELMODE::FALLBACK;
1089 m_hwaccel_enable_dec_buffering = false;
1090 m_dec_hw_pix_fmt = AV_PIX_FMT_NONE;
1091
1092 // Free hardware device contexts if open
1093 hwdevice_ctx_free(&m_hwaccel_dec_device_ctx);
1094
1095 m_in.m_video.reset();
1096
1097 // Try again with a software decoder
1098 continue;
1099 }
1100
1101 Logging::error(filename(), "Failed to open %1 input codec for stream #%1 (error '%2').", get_media_type_string(mediatype), input_stream->index, ffmpeg_geterror(ret).c_str());
1102 return ret;
1103 }
1104
1105 Logging::debug(filename(), "Opened input codec for stream #%1: %2", input_stream->index, get_codec_name(codec_id, true));
1106
1107 *codec_ctx = input_codec_ctx;
1108
1109 return 0;
1110 };
1111}
1112
1114{
1115 const AVCodec * output_codec = nullptr;
1116 AVCodecContext *output_codec_ctx = nullptr;
1117 AVDictionary * opt = nullptr;
1118 int ret = 0;
1119
1120 m_buffer = buffer;
1121 {
1122 std::lock_guard<std::recursive_mutex> lock_seek_to_fifo_mutex(m_seek_to_fifo_mutex);
1123 while (m_seek_to_fifo.size())
1124 {
1125 m_seek_to_fifo.pop();
1126 }
1127 }
1128 m_have_seeked = false;
1129
1130 output_codec = avcodec_find_encoder(m_current_format->video_codec());
1131 if (output_codec == nullptr)
1132 {
1133 Logging::error(virtname(), "Codec not found.");
1134 return AVERROR(EINVAL);
1135 }
1136
1137 output_codec_ctx = avcodec_alloc_context3(output_codec);
1138 if (output_codec_ctx == nullptr)
1139 {
1140 Logging::error(virtname(), "The video codec context could not be allocated.");
1141 return AVERROR(ENOMEM);
1142 }
1143
1144 output_codec_ctx->bit_rate = 400000;
1145 output_codec_ctx->width = m_in.m_video.m_codec_ctx->width;
1146 output_codec_ctx->height = m_in.m_video.m_codec_ctx->height;
1147 output_codec_ctx->time_base = {1, 25};
1148
1149 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(m_in.m_video.m_codec_ctx->pix_fmt);
1150 int loss = 0;
1151
1152 output_codec_ctx->pix_fmt = avcodec_find_best_pix_fmt_of_list(output_codec->pix_fmts, m_in.m_video.m_codec_ctx->pix_fmt, (dst_desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? 1 : 0, &loss);
1153
1154 if (output_codec_ctx->pix_fmt == AV_PIX_FMT_NONE)
1155 {
1156 // No best match found, use default
1157 switch (m_current_format->video_codec())
1158 {
1159 case AV_CODEC_ID_MJPEG:
1160 {
1161 output_codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ444P;
1162 break;
1163 }
1164 case AV_CODEC_ID_PNG:
1165 {
1166 output_codec_ctx->pix_fmt = AV_PIX_FMT_RGB24;
1167 break;
1168 }
1169 case AV_CODEC_ID_BMP:
1170 {
1171 output_codec_ctx->pix_fmt = AV_PIX_FMT_BGR24;
1172 break;
1173 }
1174 default:
1175 {
1176 break;
1177 }
1178 }
1179 Logging::debug(virtname(), "There was no best match output pixel format found, so we used the default: %1", get_pix_fmt_name(output_codec_ctx->pix_fmt).c_str());
1180 }
1181 else
1182 {
1183 Logging::debug(virtname(), "Output pixel format: %1", get_pix_fmt_name(output_codec_ctx->pix_fmt).c_str());
1184 }
1185
1186
1187 switch (m_current_format->video_codec())
1188 {
1189 case AV_CODEC_ID_MJPEG:
1190 {
1191 // set -strict -1 for JPG
1192 dict_set_with_check(&opt, "strict", "-1", 0);
1193
1194 // Allow the use of unoffical extensions
1195 output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
1196 break;
1197 }
1198 case AV_CODEC_ID_PNG:
1199 {
1200 output_codec_ctx->pix_fmt = AV_PIX_FMT_RGB24;
1201 break;
1202 }
1203 case AV_CODEC_ID_BMP:
1204 {
1205 output_codec_ctx->pix_fmt = AV_PIX_FMT_BGR24;
1206 break;
1207 }
1208 default:
1209 {
1210 break;
1211 }
1212 }
1213
1214 //codec_ctx->sample_aspect_ratio = frame->sample_aspect_ratio;
1215 //codec_ctx->sample_aspect_ratio = m_in.m_video.m_codec_ctx->sample_aspect_ratio;
1216
1217 ret = avcodec_open2(output_codec_ctx, output_codec, &opt);
1218 if (ret < 0)
1219 {
1220 Logging::error(virtname(), "The image codec could not be opened.");
1221 return ret;
1222 }
1223
1224 // Initialise pixel format conversion and rescaling if necessary
1225 get_pix_formats(&m_in.m_pix_fmt, &m_out.m_pix_fmt, output_codec_ctx);
1226
1227 ret = init_rescaler(m_in.m_pix_fmt, m_in.m_video.m_stream->codecpar->width, m_in.m_video.m_stream->codecpar->height, m_out.m_pix_fmt, output_codec_ctx->width, output_codec_ctx->height);
1228 if (ret < 0)
1229 {
1230 return ret;
1231 }
1232
1234 {
1235 ret = init_deinterlace_filters(output_codec_ctx, m_in.m_pix_fmt, m_in.m_video.m_stream->avg_frame_rate, m_in.m_video.m_stream->time_base);
1236 if (ret < 0)
1237 {
1238 return ret;
1239 }
1240 }
1241
1242 m_out.m_video.set_codec_ctx(output_codec_ctx);
1244 m_out.m_video.m_stream = nullptr;
1245
1246 // No audio
1247 m_out.m_audio.set_codec_ctx(nullptr);
1249 m_out.m_audio.m_stream = nullptr;
1250
1251 // Open for read/write
1252 // Pre-allocate the predicted file size to reduce memory reallocations
1253 size_t buffsize = predicted_filesize() * video_frame_count();
1254
1255 if (!buffer->open_file(0, CACHE_FLAG_RW, buffsize))
1256 {
1257 return AVERROR(EPERM);
1258 }
1259
1260 return 0;
1261}
1262
1264{
1265 int ret = 0;
1266
1267 m_buffer = buffer;
1268 m_insert_keyframe = false;
1269
1270 if (!m_out.m_video_pts && is_hls())
1271 {
1273 Logging::info(virtname(), "Starting HLS segment no. %1 of %2.", m_current_segment, m_virtualfile->get_segment_count());
1274 }
1275
1276 while (true)
1277 {
1278 // Open the output file for writing. If buffer == nullptr continue using existing buffer.
1279 ret = open_output_filestreams(buffer);
1280 if (ret)
1281 {
1283 {
1284 Logging::info(virtname(), "Unable to use output codec '%1' with hardware acceleration. Falling back to software.", avcodec_get_name(m_current_format->video_codec()));
1285
1288 m_enc_hw_pix_fmt = AV_PIX_FMT_NONE;
1289
1290 // Free hardware device contexts if open
1292
1294
1295 // Try again with a software decoder
1296 continue;
1297 }
1298 return ret;
1299 }
1300 break;
1301 }
1302
1304 {
1306
1307 if (m_out.m_audio.m_codec_ctx != nullptr)
1308 {
1309 // If not just copying the stream, initialise the audio FIFO buffer to store audio samples to be encoded.
1310 ret = init_audio_fifo();
1311 if (ret)
1312 {
1313 return ret;
1314 }
1315 }
1316 }
1317
1319 {
1321 }
1322
1323 for (const auto & [key, value] : m_out.m_subtitle)
1324 {
1325 subtitle_info(true, m_out.m_format_ctx, value.m_stream);
1326 }
1327
1328 // Open for read/write
1329 // Pre-allocate the predicted file size to reduce memory reallocations
1330 size_t buffsize = predicted_filesize();
1331 if (!buffer->open_file(0, CACHE_FLAG_RW, buffsize))
1332 {
1333 return AVERROR(EPERM);
1334 }
1335
1336 ret = process_output();
1337 if (ret)
1338 {
1339 return ret;
1340 }
1341
1342 // process_output() calls avformat_write_header which feels free to change the stream time bases sometimes.
1343 // This means we have to do the following calculations here to use the correct values, otherwise this can cause
1344 // a lot of havoc.
1345
1346 if (m_in.m_audio.m_stream != nullptr && m_out.m_audio.m_stream != nullptr && m_in.m_audio.m_stream->start_time != AV_NOPTS_VALUE)
1347 {
1351 }
1352 else
1353 {
1357 {
1358 m_out.m_audio.m_stream->start_time = AV_NOPTS_VALUE;
1359 }
1360 }
1361
1362 if (m_in.m_video.m_stream != nullptr && m_out.m_video.m_stream != nullptr && m_in.m_video.m_stream->start_time != AV_NOPTS_VALUE)
1363 {
1367 }
1368 else
1369 {
1373 {
1374 m_out.m_video.m_stream->start_time = AV_NOPTS_VALUE;
1375 }
1376 }
1377
1378 for (auto & [key, value] : m_out.m_subtitle)
1379 {
1381 if (out_streamref != nullptr)
1382 {
1383 value.m_start_time = value.m_stream->start_time;
1384 out_streamref->m_start_time = ffmpeg_rescale_q_rnd(value.m_stream->start_time, value.m_stream->time_base, out_streamref->m_stream->time_base);
1385 out_streamref->m_stream->start_time = out_streamref->m_start_time;
1386 }
1387 }
1388
1391 m_out.m_last_mux_dts = AV_NOPTS_VALUE;
1392
1393 return 0;
1394}
1395
1397{
1398 // Process metadata. The decoder will call the encoder to set appropriate
1399 // tag values for the output file.
1400 int ret = process_metadata();
1401 if (ret)
1402 {
1403 return ret;
1404 }
1405
1406 // Write the header of the output file container.
1408 if (ret)
1409 {
1410 return ret;
1411 }
1412
1413 // Process album arts: copy all from source file to target.
1414 return process_albumarts();
1415}
1416
1417bool FFmpeg_Transcoder::get_output_sample_rate(int input_sample_rate, int max_sample_rate, int *output_sample_rate /*= nullptr*/)
1418{
1419 if (input_sample_rate > max_sample_rate)
1420 {
1421 if (output_sample_rate != nullptr)
1422 {
1423 *output_sample_rate = max_sample_rate;
1424 }
1425 return true;
1426 }
1427 else
1428 {
1429 if (output_sample_rate != nullptr)
1430 {
1431 *output_sample_rate = input_sample_rate;
1432 }
1433 return false;
1434 }
1435}
1436
1437bool FFmpeg_Transcoder::get_output_bit_rate(BITRATE input_bit_rate, BITRATE max_bit_rate, BITRATE * output_bit_rate /*= nullptr*/)
1438{
1439 if (!input_bit_rate || input_bit_rate > max_bit_rate)
1440 {
1441 if (output_bit_rate != nullptr)
1442 {
1443 *output_bit_rate = max_bit_rate;
1444 }
1445 return true;
1446 }
1447 else
1448 {
1449 if (output_bit_rate != nullptr)
1450 {
1451 *output_bit_rate = input_bit_rate;
1452 }
1453 return false;
1454 }
1455}
1456
1457bool FFmpeg_Transcoder::get_aspect_ratio(int width, int height, const AVRational & sar, AVRational *ar) const
1458{
1459 // Try to determine display aspect ratio
1460 AVRational dar;
1461
1462 ::av_reduce(&dar.num, &dar.den,
1463 static_cast<int64_t>(width) * sar.num,
1464 static_cast<int64_t>(height) * sar.den,
1465 1024 * 1024);
1466
1467 ar->num = ar->den = 0;
1468
1469 if (dar.num && dar.den)
1470 {
1471 *ar = dar;
1472 }
1473
1474 // If that fails, try sample aspect ratio instead
1475 if (!ar->den && sar.num != 0 && sar.den != 0)
1476 {
1477 *ar = sar;
1478 }
1479
1480 // If even that fails, try to use video size
1481 if (!ar->den && height)
1482 {
1483 ar->num = width;
1484 ar->den = height;
1485 }
1486
1487 if (!ar->den)
1488 {
1489 // Return false if all above failed
1490 return false;
1491 }
1492
1493 ::av_reduce(&ar->num, &ar->den,
1494 ar->num,
1495 ar->den,
1496 1024 * 1024);
1497
1498 return true;
1499}
1500
1501bool FFmpeg_Transcoder::get_video_size(int *output_width, int *output_height) const
1502{
1504 {
1505 // No options, leave as is
1506 return false;
1507 }
1508
1509 int input_width = m_in.m_video.m_stream->codecpar->width;
1510 int input_height = m_in.m_video.m_stream->codecpar->height;
1511 AVRational sar = m_in.m_video.m_stream->codecpar->sample_aspect_ratio;
1512
1514 {
1515 // Both width/source set. May look strange, but this is an order...
1516 *output_width = params.m_videowidth;
1517 *output_height = params.m_videoheight;
1518 }
1519 else if (params.m_videowidth)
1520 {
1521 // Only video width
1522 AVRational ar;
1523
1524 *output_width = params.m_videowidth;
1525
1526 if (!get_aspect_ratio(input_width, input_height, sar, &ar))
1527 {
1528 *output_height = input_height;
1529 }
1530 else
1531 {
1532 *output_height = static_cast<int>(params.m_videowidth / av_q2d(ar));
1533 *output_height &= ~(static_cast<int>(0x1)); // height must be multiple of 2
1534 }
1535 }
1536 else //if (params.m_videoheight)
1537 {
1538 // Only video height
1539 AVRational ar;
1540
1541 if (!get_aspect_ratio(input_width, input_height, sar, &ar))
1542 {
1543 *output_width = input_width;
1544 }
1545 else
1546 {
1547 *output_width = static_cast<int>(params.m_videoheight / av_q2d(ar));
1548 *output_width &= ~(static_cast<int>(0x1)); // width must be multiple of 2
1549 }
1550 *output_height = params.m_videoheight;
1551 }
1552
1553 return (input_width > *output_width || input_height > *output_height);
1554}
1555
1556int FFmpeg_Transcoder::update_codec(void *opt, const PROFILE_OPTION_VEC& profile_option_vec) const
1557{
1558 int ret = 0;
1559
1560 for (const PROFILE_OPTION & profile_option : profile_option_vec)
1561 {
1562 if ((m_hwaccel_enable_enc_buffering && profile_option.m_options & OPT_SW_ONLY) || (!m_hwaccel_enable_enc_buffering && profile_option.m_options & OPT_HW_ONLY))
1563 {
1564 continue;
1565 }
1566
1567 Logging::trace(virtname(), "Profile codec option -%1%2%3.", profile_option.m_key, *profile_option.m_value ? " " : "", profile_option.m_value);
1568
1569 ret = opt_set_with_check(opt, profile_option.m_key, profile_option.m_value, profile_option.m_flags, virtname());
1570 if (ret < 0)
1571 {
1572 break;
1573 }
1574 }
1575 return ret;
1576}
1577
1578int FFmpeg_Transcoder::prepare_codec(void *opt, FILETYPE filetype) const
1579{
1580 int ret = 0;
1581
1582 for (const PROFILE_LIST & profile : m_profile)
1583 {
1584 if (profile.m_filetype == filetype && profile.m_profile == params.m_profile)
1585 {
1586 ret = update_codec(opt, profile.m_option_codec);
1587 break;
1588 }
1589 }
1590
1591 return ret;
1592}
1593
1594int FFmpeg_Transcoder::init_rescaler(AVPixelFormat in_pix_fmt, int in_width, int in_height, AVPixelFormat out_pix_fmt, int out_width, int out_height)
1595{
1596 if (in_pix_fmt != out_pix_fmt || in_width != out_width || in_height != out_height)
1597 {
1598 // Rescale image if required
1599 if (in_pix_fmt != out_pix_fmt)
1600 {
1601 Logging::trace(virtname(), "Initialising pixel format conversion from %1 to %2.", get_pix_fmt_name(in_pix_fmt).c_str(), get_pix_fmt_name(out_pix_fmt).c_str());
1602 }
1603
1604 if (in_width != out_width || in_height != out_height)
1605 {
1606 Logging::debug(virtname(), "Rescaling video size from %1:%2 to %3:%4.",
1607 in_width, in_height,
1608 out_width, out_height);
1609 }
1610
1611 m_sws_ctx = sws_getContext(
1612 // Source settings
1613 in_width, // width
1614 in_height, // height
1615 in_pix_fmt, // format
1616 // Target settings
1617 out_width, // width
1618 out_height, // height
1619 out_pix_fmt, // format
1620 SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); // Maybe SWS_LANCZOS | SWS_ACCURATE_RND
1621 if (m_sws_ctx == nullptr)
1622 {
1623 Logging::error(virtname(), "Could not allocate a scaling/conversion context.");
1624 return AVERROR(ENOMEM);
1625 }
1626 }
1627
1628 return 0;
1629}
1630
1631int FFmpeg_Transcoder::add_stream(AVCodecID codec_id)
1632{
1633 AVCodecContext *output_codec_ctx = nullptr;
1634 AVStream * output_stream = nullptr;
1635#if IF_DECLARED_CONST
1636 const AVCodec * output_codec = nullptr;
1637#else // !IF_DECLARED_CONST
1638 AVCodec * output_codec = nullptr;
1639#endif // !IF_DECLARED_CONST
1640 AVDictionary * opt = nullptr;
1641 int ret;
1642
1643 std::string codec_name;
1644
1645 if (get_hw_encoder_name(codec_id, &codec_name) || m_hwaccel_enc_mode == HWACCELMODE::FALLBACK)
1646 {
1647 // find the encoder
1648 output_codec = avcodec_find_encoder(codec_id);
1649
1650 if (output_codec == nullptr)
1651 {
1652 Logging::error(virtname(), "Could not find encoder '%1'.", avcodec_get_name(codec_id));
1653 return AVERROR(EINVAL);
1654 }
1655 }
1656 else
1657 {
1658 output_codec = avcodec_find_encoder_by_name(codec_name.c_str());
1659
1660 if (output_codec == nullptr)
1661 {
1662 Logging::error(virtname(), "Could not find encoder '%1'.", codec_name.c_str());
1663 return AVERROR(EINVAL);
1664 }
1665
1666 //Logging::info(virtname(), "Hardware encoder acceleration active with codec '%1'.", output_codec->name);
1667
1669 }
1670
1671 output_stream = avformat_new_stream(m_out.m_format_ctx, output_codec);
1672 if (output_stream == nullptr)
1673 {
1674 Logging::error(virtname(), "Could not allocate stream for encoder '%1'.", avcodec_get_name(codec_id));
1675 return AVERROR(ENOMEM);
1676 }
1677 output_stream->id = static_cast<int>(m_out.m_format_ctx->nb_streams - 1);
1678
1679 output_codec_ctx = avcodec_alloc_context3(output_codec);
1680 if (output_codec_ctx == nullptr)
1681 {
1682 Logging::error(virtname(), "Could not allocate an encoding context.");
1683 return AVERROR(ENOMEM);
1684 }
1685
1686 switch (output_codec->type)
1687 {
1688 case AVMEDIA_TYPE_AUDIO:
1689 {
1690 BITRATE orig_bit_rate;
1691 int orig_sample_rate;
1692
1693 // Set the basic encoder parameters
1694 orig_bit_rate = (m_in.m_audio.m_stream->codecpar->bit_rate != 0) ? m_in.m_audio.m_stream->codecpar->bit_rate : m_in.m_format_ctx->bit_rate;
1695 if (get_output_bit_rate(orig_bit_rate, params.m_audiobitrate, &output_codec_ctx->bit_rate))
1696 {
1697 // Limit bit rate
1698 Logging::trace(virtname(), "Limiting audio bit rate from %1 to %2.",
1699 format_bitrate(orig_bit_rate).c_str(),
1700 format_bitrate(output_codec_ctx->bit_rate).c_str());
1701 }
1702
1704 {
1705 Logging::trace(virtname(), "Limiting audio channels from %1 to %2.",
1708 set_channels(output_codec_ctx, params.m_audiochannels);
1709 }
1710 else
1711 {
1712 set_channels(output_codec_ctx, m_in.m_audio.m_codec_ctx.get());
1713 }
1714
1715#if LAVU_DEP_OLD_CHANNEL_LAYOUT
1716 av_channel_layout_default(&output_codec_ctx->ch_layout, output_codec_ctx->ch_layout.nb_channels);
1717#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
1718 output_codec_ctx->channel_layout = static_cast<uint64_t>(av_get_default_channel_layout(output_codec_ctx->channels));
1719#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
1720
1721 output_codec_ctx->sample_rate = m_in.m_audio.m_codec_ctx->sample_rate;
1722 orig_sample_rate = m_in.m_audio.m_codec_ctx->sample_rate;
1723 if (get_output_sample_rate(m_in.m_audio.m_stream->codecpar->sample_rate, params.m_audiosamplerate, &output_codec_ctx->sample_rate))
1724 {
1725 // Limit sample rate
1726 Logging::trace(virtname(), "Limiting audio sample rate from %1 to %2.",
1727 format_samplerate(orig_sample_rate).c_str(),
1728 format_samplerate(output_codec_ctx->sample_rate).c_str());
1729 orig_sample_rate = output_codec_ctx->sample_rate;
1730 }
1731
1732 if (output_codec->supported_samplerates != nullptr)
1733 {
1734 // Go through supported sample rates and adjust if necessary
1735 bool supported = false;
1736
1737 for (int n = 0; output_codec->supported_samplerates[n] != 0; n++)
1738 {
1739 if (output_codec->supported_samplerates[n] == output_codec_ctx->sample_rate)
1740 {
1741 // Is supported
1742 supported = true;
1743 break;
1744 }
1745 }
1746
1747 if (!supported)
1748 {
1749 int min_samplerate = 0;
1750 int max_samplerate = INT_MAX;
1751
1752 // Find next lower sample rate in probably unsorted list
1753 for (int n = 0; output_codec->supported_samplerates[n] != 0; n++)
1754 {
1755 if (min_samplerate <= output_codec->supported_samplerates[n] && output_codec_ctx->sample_rate >= output_codec->supported_samplerates[n])
1756 {
1757 min_samplerate = output_codec->supported_samplerates[n];
1758 }
1759 }
1760
1761 // Find next higher sample rate in probably unsorted list
1762 for (int n = 0; output_codec->supported_samplerates[n] != 0; n++)
1763 {
1764 if (max_samplerate >= output_codec->supported_samplerates[n] && output_codec_ctx->sample_rate <= output_codec->supported_samplerates[n])
1765 {
1766 max_samplerate = output_codec->supported_samplerates[n];
1767 }
1768 }
1769
1770 if (min_samplerate != 0 && max_samplerate != INT_MAX)
1771 {
1772 // set to nearest value
1773 if (output_codec_ctx->sample_rate - min_samplerate < max_samplerate - output_codec_ctx->sample_rate)
1774 {
1775 output_codec_ctx->sample_rate = min_samplerate;
1776 }
1777 else
1778 {
1779 output_codec_ctx->sample_rate = max_samplerate;
1780 }
1781 }
1782 else if (min_samplerate != 0)
1783 {
1784 // No higher sample rate, use next lower
1785 output_codec_ctx->sample_rate = min_samplerate;
1786 }
1787 else if (max_samplerate != INT_MAX)
1788 {
1789 // No lower sample rate, use higher lower
1790 output_codec_ctx->sample_rate = max_samplerate;
1791 }
1792 else
1793 {
1794 // Should never happen... There must at least be one.
1795 Logging::error(virtname(), "The codec does not support an audio sample rate of %1.", format_samplerate(output_codec_ctx->sample_rate).c_str());
1796 return AVERROR(EINVAL);
1797 }
1798
1799 Logging::debug(virtname(), "Because the requested value is not supported by codec, the audio sample rate was changed from %1 to %2.",
1800 format_samplerate(orig_sample_rate).c_str(),
1801 format_samplerate(output_codec_ctx->sample_rate).c_str());
1802 }
1803 }
1804
1805 // If sample format not pre-defined (not AV_SAMPLE_FMT_NONE), use input file setting.
1806 AVSampleFormat in_sample_format = (m_current_format->sample_format() == AV_SAMPLE_FMT_NONE) ? m_in.m_audio.m_codec_ctx->sample_fmt : m_current_format->sample_format();
1807 if (output_codec->sample_fmts != nullptr)
1808 {
1809 // Check if input sample format is supported and if so, use it (avoiding resampling)
1810 AVSampleFormat input_fmt_planar = av_get_planar_sample_fmt(in_sample_format);
1811
1812 output_codec_ctx->sample_fmt = AV_SAMPLE_FMT_NONE;
1813
1814 for (const AVSampleFormat *sample_fmt = output_codec->sample_fmts; *sample_fmt != -1; sample_fmt++)
1815 {
1816 AVSampleFormat output_fmt_planar = av_get_planar_sample_fmt(*sample_fmt);
1817
1818 if (*sample_fmt == in_sample_format ||
1819 (input_fmt_planar != AV_SAMPLE_FMT_NONE &&
1820 input_fmt_planar == output_fmt_planar))
1821 {
1822 output_codec_ctx->sample_fmt = *sample_fmt;
1823 break;
1824 }
1825 }
1826
1827 // If none of the supported formats match use the first supported
1828 if (output_codec_ctx->sample_fmt == AV_SAMPLE_FMT_NONE)
1829 {
1830 output_codec_ctx->sample_fmt = output_codec->sample_fmts[0];
1831 }
1832 }
1833 else
1834 {
1835 // If supported sample formats are unknown simply take input format and cross our fingers it'll work...
1836 output_codec_ctx->sample_fmt = in_sample_format;
1837 }
1838
1839 // Set the sample rate for the container.
1840 output_stream->time_base.den = output_codec_ctx->sample_rate;
1841 output_stream->time_base.num = 1;
1842 output_codec_ctx->time_base = output_stream->time_base;
1843
1844 // set -strict -2 for aac (required for FFmpeg 2)
1845 dict_set_with_check(&opt, "strict", "-2", 0);
1846
1847 // Allow the use of the experimental AAC encoder
1848 output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
1849
1850 // Set duration as hint for muxer
1851 if (m_in.m_audio.m_stream->duration != AV_NOPTS_VALUE)
1852 {
1853 output_stream->duration = ffmpeg_rescale_q(m_in.m_audio.m_stream->duration, m_in.m_audio.m_stream->time_base, output_stream->time_base);
1854 }
1855 else if (m_in.m_format_ctx->duration != AV_NOPTS_VALUE)
1856 {
1857 output_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), output_stream->time_base);
1858 }
1859
1860 //av_dict_set_int(&output_stream->metadata, "DURATION", output_stream->duration, AV_DICT_IGNORE_SUFFIX);
1861
1862 // Save the encoder context for easier access later.
1863 m_out.m_audio.set_codec_ctx(output_codec_ctx);
1864 // Save the stream index
1865 m_out.m_audio.m_stream_idx = output_stream->index;
1866 // Save output audio stream for faster reference
1867 m_out.m_audio.m_stream = output_stream;
1868
1869 // Update input to output stream map, this is rather boring because currently we only have a single audio stream
1871 break;
1872 }
1873 case AVMEDIA_TYPE_VIDEO:
1874 {
1875 BITRATE orig_bit_rate;
1876
1878 {
1879 Logging::debug(virtname(), "Hardware encoder init: Creating a new hardware frame context for the encoder.", get_hwaccel_API_text(params.m_hwaccel_enc_API).c_str());
1880
1882
1883 ret = hwframe_ctx_set(output_codec_ctx, m_in.m_video.m_codec_ctx.get(), m_hwaccel_enc_device_ctx);
1884 if (ret < 0)
1885 {
1886 return ret;
1887 }
1888 }
1889
1890 output_codec_ctx->codec_id = codec_id;
1891
1892 // Set the basic encoder parameters
1893 orig_bit_rate = (m_in.m_video.m_stream->codecpar->bit_rate != 0) ? m_in.m_video.m_stream->codecpar->bit_rate : m_in.m_format_ctx->bit_rate;
1894 if (get_output_bit_rate(orig_bit_rate, params.m_videobitrate, &output_codec_ctx->bit_rate))
1895 {
1896 // Limit sample rate
1897 Logging::trace(virtname(), "Limiting video bit rate from %1 to %2.",
1898 format_bitrate(orig_bit_rate).c_str(),
1899 format_bitrate(output_codec_ctx->bit_rate).c_str());
1900 }
1901
1902 // output_codec_ctx->rc_min_rate = output_codec_ctx->bit_rate * 75 / 100;
1903 // output_codec_ctx->rc_max_rate = output_codec_ctx->bit_rate * 125 / 100;
1904
1905 // output_codec_ctx->qmin = 1;
1906 // output_codec_ctx->qmax = 31;
1907
1908 int width = 0;
1909 int height = 0;
1910 if (get_video_size(&width, &height))
1911 {
1912 Logging::trace(virtname(), "Changing video size from %1/%2 to %3/%4.", output_codec_ctx->width, output_codec_ctx->height, width, height);
1913 output_codec_ctx->width = width;
1914 output_codec_ctx->height = height;
1915 }
1916 else
1917 {
1918 output_codec_ctx->width = m_in.m_video.m_stream->codecpar->width;
1919 output_codec_ctx->height = m_in.m_video.m_stream->codecpar->height;
1920 }
1921
1922 video_stream_setup(output_codec_ctx, output_stream, m_in.m_video.m_codec_ctx.get(), m_in.m_video.m_stream->avg_frame_rate, m_enc_hw_pix_fmt);
1923
1924 AVRational sample_aspect_ratio = m_in.m_video.m_stream->codecpar->sample_aspect_ratio;
1925
1926 if (output_codec_ctx->codec_id != AV_CODEC_ID_VP9 && m_out.m_filetype != FILETYPE::MKV)
1927 {
1928 output_codec_ctx->sample_aspect_ratio = sample_aspect_ratio;
1929 output_stream->codecpar->sample_aspect_ratio = sample_aspect_ratio;
1930 }
1931
1932 else
1933 {
1934 // WebM and MKV do not respect the aspect ratio and always use 1:1 so we need to rescale "manually".
1941 output_codec_ctx->sample_aspect_ratio = { 1, 1 };
1942 output_stream->codecpar->sample_aspect_ratio = { 1, 1 };
1943
1944 // Make sure we do not zero width
1945 if (sample_aspect_ratio.num && sample_aspect_ratio.den)
1946 {
1947 output_codec_ctx->width = output_codec_ctx->width * sample_aspect_ratio.num / sample_aspect_ratio.den;
1948 }
1949 //output_codec_ctx->height *= sample_aspect_ratio.den;
1950 }
1951
1952 // Set up optimisations
1953 switch (output_codec_ctx->codec_id)
1954 {
1955 case AV_CODEC_ID_H264:
1956 {
1957 ret = prepare_codec(output_codec_ctx->priv_data, m_out.m_filetype);
1958 if (ret < 0)
1959 {
1960 Logging::error(virtname(), "Could not set profile for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
1961 return ret;
1962 }
1963
1965 {
1966 // For hardware encoding only
1967
1968 // Defaults to 20. Set to 40 to create slightly smaller results (the bigger, the smaller the files).
1969 // Values seem to range between 1 and 51.
1970 // Must be non-zero, otherwise hardware encoding my fail with:
1971 // "Driver does not support any RC mode compatible with selected options (supported modes: CQP)."
1972 output_codec_ctx->global_quality = 40;
1973 }
1974
1975 // Avoid mismatches for H264 and profile
1976 uint8_t *out_val;
1977 ret = av_opt_get(output_codec_ctx->priv_data, "profile", 0, &out_val);
1978 if (!ret)
1979 {
1980 if (!strcasecmp(reinterpret_cast<const char *>(out_val), "high"))
1981 {
1982 switch (output_codec_ctx->pix_fmt)
1983 {
1984 case AV_PIX_FMT_YUYV422:
1985 case AV_PIX_FMT_YUV422P:
1986 case AV_PIX_FMT_YUVJ422P:
1987 case AV_PIX_FMT_UYVY422:
1988 case AV_PIX_FMT_YUV422P16LE:
1989 case AV_PIX_FMT_YUV422P16BE:
1990 case AV_PIX_FMT_YUV422P10BE:
1991 case AV_PIX_FMT_YUV422P10LE:
1992 case AV_PIX_FMT_YUV422P9BE:
1993 case AV_PIX_FMT_YUV422P9LE:
1994 case AV_PIX_FMT_YUVA422P9BE:
1995 case AV_PIX_FMT_YUVA422P9LE:
1996 case AV_PIX_FMT_YUVA422P10BE:
1997 case AV_PIX_FMT_YUVA422P10LE:
1998 case AV_PIX_FMT_YUVA422P16BE:
1999 case AV_PIX_FMT_YUVA422P16LE:
2000 case AV_PIX_FMT_NV16:
2001 case AV_PIX_FMT_NV20LE:
2002 case AV_PIX_FMT_NV20BE:
2003 case AV_PIX_FMT_YVYU422:
2004 case AV_PIX_FMT_YUVA422P:
2005 case AV_PIX_FMT_YUV422P12BE:
2006 case AV_PIX_FMT_YUV422P12LE:
2007 case AV_PIX_FMT_YUV422P14BE:
2008 case AV_PIX_FMT_YUV422P14LE:
2009 {
2010 ret = av_opt_set(output_codec_ctx->priv_data, "profile", "high422", 0);
2011 if (ret < 0)
2012 {
2013 Logging::error(virtname(), "Could not set profile=high422 for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
2014 return ret;
2015 }
2016 break;
2017 }
2018 case AV_PIX_FMT_YUV444P:
2019 case AV_PIX_FMT_YUVJ444P:
2020 case AV_PIX_FMT_YUV444P16LE:
2021 case AV_PIX_FMT_YUV444P16BE:
2022 case AV_PIX_FMT_RGB444LE:
2023 case AV_PIX_FMT_RGB444BE:
2024 case AV_PIX_FMT_BGR444LE:
2025 case AV_PIX_FMT_BGR444BE:
2026 case AV_PIX_FMT_YUV444P9BE:
2027 case AV_PIX_FMT_YUV444P9LE:
2028 case AV_PIX_FMT_YUV444P10BE:
2029 case AV_PIX_FMT_YUV444P10LE:
2030 case AV_PIX_FMT_GBRP:
2031 case AV_PIX_FMT_GBRP9BE:
2032 case AV_PIX_FMT_GBRP9LE:
2033 case AV_PIX_FMT_GBRP10BE:
2034 case AV_PIX_FMT_GBRP10LE:
2035 case AV_PIX_FMT_GBRP16BE:
2036 case AV_PIX_FMT_GBRP16LE:
2037 case AV_PIX_FMT_YUVA444P9BE:
2038 case AV_PIX_FMT_YUVA444P9LE:
2039 case AV_PIX_FMT_YUVA444P10BE:
2040 case AV_PIX_FMT_YUVA444P10LE:
2041 case AV_PIX_FMT_YUVA444P16BE:
2042 case AV_PIX_FMT_YUVA444P16LE:
2043 case AV_PIX_FMT_XYZ12LE:
2044 case AV_PIX_FMT_XYZ12BE:
2045 case AV_PIX_FMT_YUVA444P:
2046 case AV_PIX_FMT_GBRAP:
2047 case AV_PIX_FMT_GBRAP16BE:
2048 case AV_PIX_FMT_GBRAP16LE:
2049 case AV_PIX_FMT_YUV444P12BE:
2050 case AV_PIX_FMT_YUV444P12LE:
2051 case AV_PIX_FMT_YUV444P14BE:
2052 case AV_PIX_FMT_YUV444P14LE:
2053 case AV_PIX_FMT_GBRP12BE:
2054 case AV_PIX_FMT_GBRP12LE:
2055 case AV_PIX_FMT_GBRP14BE:
2056 case AV_PIX_FMT_GBRP14LE:
2057 case AV_PIX_FMT_AYUV64LE:
2058 case AV_PIX_FMT_AYUV64BE:
2059 {
2060 ret = av_opt_set(output_codec_ctx->priv_data, "profile", "high444", 0);
2061 if (ret < 0)
2062 {
2063 Logging::error(virtname(), "Could not set profile=high444 for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
2064 return ret;
2065 }
2066 break;
2067 }
2068 default:
2069 {
2070 break;
2071 }
2072 }
2073 }
2074 av_free(out_val);
2075 }
2076 break;
2077 }
2078 case AV_CODEC_ID_VP9:
2079 {
2080 ret = prepare_codec(output_codec_ctx->priv_data, FILETYPE::WEBM);
2081 if (ret < 0)
2082 {
2083 Logging::error(virtname(), "Could not set profile for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
2084 return ret;
2085 }
2086 break;
2087 }
2088 case AV_CODEC_ID_PRORES:
2089 {
2090 ret = prepare_codec(output_codec_ctx->priv_data, FILETYPE::PRORES);
2091 if (ret < 0)
2092 {
2093 Logging::error(virtname(), "Could not set profile for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
2094 return ret;
2095 }
2096
2097 // 0 = ‘proxy’,
2098 // 1 = ‘lt’,
2099 // 2 = ‘standard’,
2100 // 3 = ‘hq’
2101 output_codec_ctx->profile = static_cast<int>(params.m_level);
2102 break;
2103 }
2104 case AV_CODEC_ID_ALAC:
2105 {
2106 ret = prepare_codec(output_codec_ctx->priv_data, FILETYPE::ALAC);
2107 if (ret < 0)
2108 {
2109 Logging::error(virtname(), "Could not set profile for %1 output codec %2 (error '%3').", get_media_type_string(output_codec->type), get_codec_name(codec_id), ffmpeg_geterror(ret).c_str());
2110 return ret;
2111 }
2112 break;
2113 }
2114 default:
2115 {
2116 break;
2117 }
2118 }
2119
2120 // Initialise pixel format conversion and rescaling if necessary
2121 get_pix_formats(&m_in.m_pix_fmt, &m_out.m_pix_fmt, output_codec_ctx);
2122
2123 ret = init_rescaler(m_in.m_pix_fmt, m_in.m_video.m_stream->codecpar->width, m_in.m_video.m_stream->codecpar->height, m_out.m_pix_fmt, output_codec_ctx->width, output_codec_ctx->height);
2124 if (ret < 0)
2125 {
2126 return ret;
2127 }
2128
2129 // set -strict -2 for aac (required for FFmpeg 2)
2130 dict_set_with_check(&opt, "strict", "-2", 0);
2131
2132 // Allow the use of the experimental AAC encoder
2133 output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
2134
2135#ifdef _DEBUG
2136 print_stream_info(output_stream);
2137#endif // _DEBUG
2138
2139 // Set duration as hint for muxer
2140 if (m_in.m_video.m_stream->duration != AV_NOPTS_VALUE)
2141 {
2142 output_stream->duration = ffmpeg_rescale_q(m_in.m_video.m_stream->duration, m_in.m_video.m_stream->time_base, output_stream->time_base);
2143 }
2144 else if (m_in.m_format_ctx->duration != AV_NOPTS_VALUE)
2145 {
2146 output_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), output_stream->time_base);
2147 }
2148
2149 //av_dict_set_int(&output_stream->metadata, "DURATION", output_stream->duration, AV_DICT_IGNORE_SUFFIX);
2150
2151 // Save the encoder context for easier access later.
2152 m_out.m_video.set_codec_ctx(output_codec_ctx);
2153 // Save the stream index
2154 m_out.m_video.m_stream_idx = output_stream->index;
2155 // Save output video stream for faster reference
2156 m_out.m_video.m_stream = output_stream;
2157
2158 // Update input to output stream map, this is rather boring because currently we only have a single video stream
2160 break;
2161 }
2162 default:
2163 break;
2164 }
2165
2166 // Although docs state this is "Demuxing only", this is actually used by encoders like Matroska/WebM, so we need to set this here.
2167 m_out.m_format_ctx->duration = m_in.m_format_ctx->duration;
2169 {
2170 av_dict_set_int(&m_out.m_format_ctx->metadata, "DURATION", m_virtualfile->m_cuesheet_track.m_duration, AV_DICT_IGNORE_SUFFIX);
2171 }
2172 else
2173 {
2174 av_dict_set_int(&m_out.m_format_ctx->metadata, "DURATION", m_out.m_format_ctx->duration, AV_DICT_IGNORE_SUFFIX);
2175 }
2176
2177 // Some formats want stream headers to be separate.
2178 if (m_out.m_format_ctx->oformat->flags & AVFMT_GLOBALHEADER)
2179 {
2180 output_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
2181 }
2182
2183 if (!av_dict_get(opt, "threads", nullptr, 0))
2184 {
2185 Logging::trace(virtname(), "Setting threads to auto for codec %1.", get_codec_name(output_codec_ctx->codec_id));
2186 dict_set_with_check(&opt, "threads", "auto", 0, virtname());
2187 }
2188
2189 // Open the encoder for the stream to use it later.
2190 ret = avcodec_open2(output_codec_ctx, output_codec, &opt);
2191 if (ret < 0)
2192 {
2193 Logging::error(virtname(), "Could not open %1 output codec %2 for stream #%3 (error '%4').", get_media_type_string(output_codec->type), get_codec_name(codec_id), output_stream->index, ffmpeg_geterror(ret).c_str());
2194 return ret;
2195 }
2196
2197 Logging::debug(virtname(), "Opened %1 output codec %2 for stream #%3.", get_media_type_string(output_codec->type), get_codec_name(codec_id, true), output_stream->index);
2198
2199 ret = avcodec_parameters_from_context(output_stream->codecpar, output_codec_ctx);
2200 if (ret < 0)
2201 {
2202 Logging::error(virtname(), "Could not initialise stream parameters (error '%1').", ffmpeg_geterror(ret).c_str());
2203 return ret;
2204 }
2205
2206 return (output_stream->index);
2207}
2208
2209int FFmpeg_Transcoder::add_subtitle_stream(AVCodecID codec_id, StreamRef & input_streamref, const std::optional<std::string> & language)
2210{
2211 AVCodecContext *output_codec_ctx = nullptr;
2212 AVStream * output_stream = nullptr;
2213#if IF_DECLARED_CONST
2214 const AVCodec * output_codec = nullptr;
2215#else // !IF_DECLARED_CONST
2216 AVCodec * output_codec = nullptr;
2217#endif // !IF_DECLARED_CONST
2218 AVDictionary * opt = nullptr;
2219 int ret;
2220
2221 // find the encoder
2222 output_codec = avcodec_find_encoder(codec_id);
2223
2224 if (output_codec == nullptr)
2225 {
2226 Logging::error(virtname(), "'%1' encoder could not be found.", avcodec_get_name(codec_id));
2227 return AVERROR(EINVAL);
2228 }
2229
2230 output_stream = avformat_new_stream(m_out.m_format_ctx, output_codec);
2231 if (output_stream == nullptr)
2232 {
2233 Logging::error(virtname(), "Could not allocate stream for encoder '%1'.", avcodec_get_name(codec_id));
2234 return AVERROR(ENOMEM);
2235 }
2236 output_stream->id = static_cast<int>(m_out.m_format_ctx->nb_streams - 1);
2237
2238 output_codec_ctx = avcodec_alloc_context3(output_codec);
2239 if (output_codec_ctx == nullptr)
2240 {
2241 Logging::error(virtname(), "Could not allocate an encoding context for encoder '%1'.", avcodec_get_name(codec_id));
2242 return AVERROR(ENOMEM);
2243 }
2244
2245 output_stream->time_base = input_streamref.m_stream->time_base;
2246 output_codec_ctx->time_base = output_stream->time_base;
2247
2248 // set -strict -2 for aac (required for FFmpeg 2)
2249 dict_set_with_check(&opt, "strict", "-2", 0);
2250
2251 // Allow the use of the experimental AAC encoder
2252 output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
2253
2254 // Set duration as hint for muxer
2255 if (m_in.m_video.m_stream != nullptr && m_in.m_video.m_stream->duration != AV_NOPTS_VALUE)
2256 {
2257 output_stream->duration = ffmpeg_rescale_q(m_in.m_video.m_stream->duration, m_in.m_video.m_stream->time_base, output_stream->time_base);
2258 }
2259 if (m_in.m_audio.m_stream != nullptr && m_in.m_audio.m_stream->duration != AV_NOPTS_VALUE)
2260 {
2261 output_stream->duration = ffmpeg_rescale_q(m_in.m_audio.m_stream->duration, m_in.m_audio.m_stream->time_base, output_stream->time_base);
2262 }
2263 else if (m_in.m_format_ctx != nullptr && m_in.m_format_ctx->duration != AV_NOPTS_VALUE)
2264 {
2265 output_stream->duration = ffmpeg_rescale_q(m_in.m_format_ctx->duration, av_get_time_base_q(), output_stream->time_base);
2266 }
2267
2268 AVCodecContext * input_codec_ctx = input_streamref.m_codec_ctx.get();
2269
2270 if (input_codec_ctx != nullptr && input_codec_ctx->subtitle_header != nullptr)
2271 {
2272 // ASS code assumes this buffer is null terminated so add extra byte.
2273 output_codec_ctx->subtitle_header = static_cast<uint8_t *>(av_mallocz(static_cast<size_t>(input_codec_ctx->subtitle_header_size) + 1));
2274 if (output_codec_ctx->subtitle_header == nullptr)
2275 {
2276 return AVERROR(ENOMEM);
2277 }
2278 std::memcpy(output_codec_ctx->subtitle_header, input_codec_ctx->subtitle_header, static_cast<size_t>(input_codec_ctx->subtitle_header_size));
2279 output_codec_ctx->subtitle_header_size = input_codec_ctx->subtitle_header_size;
2280 }
2281 else if (output_codec_ctx->codec_id == AV_CODEC_ID_WEBVTT || output_codec_ctx->codec_id == AV_CODEC_ID_SUBRIP)
2282 {
2283 // If source had no header, we create a default one
2284 ret = get_script_info(output_codec_ctx,
2290
2291 if (ret)
2292 {
2293 Logging::error(virtname(), "Could not create ASS script info for encoder '%1'.", avcodec_get_name(codec_id));
2294 return ret;
2295 }
2296 }
2297
2298 // Open the encoder for the stream to use it later.
2299 ret = avcodec_open2(output_codec_ctx, output_codec, &opt);
2300 if (ret < 0)
2301 {
2302 Logging::error(virtname(), "Could not open %1 output codec %2 for stream #%3 (error '%4').", get_media_type_string(output_codec->type), get_codec_name(codec_id), output_stream->index, ffmpeg_geterror(ret).c_str());
2303 return ret;
2304 }
2305
2306 Logging::debug(virtname(), "Opened %1 output codec %2 for stream #%3.", get_media_type_string(output_codec->type), get_codec_name(codec_id, true), output_stream->index);
2307
2308 ret = avcodec_parameters_from_context(output_stream->codecpar, output_codec_ctx);
2309 if (ret < 0)
2310 {
2311 Logging::error(virtname(), "Could not initialise stream parameters (error '%1').", ffmpeg_geterror(ret).c_str());
2312 return ret;
2313 }
2314
2315 if (!language)
2316 {
2317 // Copy language
2318 AVDictionaryEntry *tag = nullptr;
2319
2320 tag = av_dict_get(input_streamref.m_stream->metadata, "language", nullptr, AV_DICT_IGNORE_SUFFIX);
2321 if (tag != nullptr)
2322 {
2323 av_dict_set(&output_stream->metadata, "language", tag->value, AV_DICT_IGNORE_SUFFIX);
2324 }
2325 }
2326 else
2327 {
2328 // Use predefined value
2329 av_dict_set(&output_stream->metadata, "language", language->c_str(), AV_DICT_IGNORE_SUFFIX);
2330 }
2331
2332 // Save the encoder context for easier access later.
2333 StreamRef output_streamref;
2334
2335 output_streamref.set_codec_ctx(output_codec_ctx);
2336 // Save the stream index
2337 output_streamref.m_stream_idx = output_stream->index;
2338 // Save output audio stream for faster reference
2339 output_streamref.m_stream = output_stream;
2340
2341 m_out.m_subtitle.insert(std::make_pair(output_streamref.m_stream_idx, output_streamref));
2342
2343 // Update input to output stream map
2344 add_stream_map(input_streamref.m_stream_idx, output_streamref.m_stream_idx);
2345
2346 return output_streamref.m_stream_idx;
2347}
2348
2349int FFmpeg_Transcoder::add_stream_copy(AVCodecID codec_id, AVMediaType codec_type)
2350{
2351 AVStream * output_stream = nullptr;
2352 int ret;
2353
2354 output_stream = avformat_new_stream(m_out.m_format_ctx, nullptr);
2355 if (output_stream == nullptr)
2356 {
2357 Logging::error(virtname(), "Could not allocate stream for encoder '%1'.", avcodec_get_name(codec_id));
2358 return AVERROR(ENOMEM);
2359 }
2360 output_stream->id = static_cast<int>(m_out.m_format_ctx->nb_streams - 1);
2361
2362 switch (codec_type)
2363 {
2364 case AVMEDIA_TYPE_AUDIO:
2365 {
2366 ret = avcodec_parameters_copy(output_stream->codecpar, m_in.m_audio.m_stream->codecpar);
2367 if (ret < 0)
2368 {
2369 Logging::error(virtname(), "Could not allocate an encoding context (error '%2').", ffmpeg_geterror(ret).c_str());
2370 return ret;
2371 }
2372
2373 // Set the sample rate for the container.
2374 output_stream->time_base = m_in.m_audio.m_stream->time_base;
2375
2376 // Set duration as hint for muxer
2377 output_stream->duration = ffmpeg_rescale_q(m_in.m_audio.m_stream->duration, m_in.m_audio.m_stream->time_base, output_stream->time_base);
2378
2379 // Save the encoder context for easier access later.
2380 m_out.m_audio.set_codec_ctx(nullptr);
2381 // Save the stream index
2382 m_out.m_audio.m_stream_idx = output_stream->index;
2383 // Save output audio stream for faster reference
2384 m_out.m_audio.m_stream = output_stream;
2385
2386 // Update input to output stream map, this is rather boring because currently we only have a single audio stream
2388 break;
2389 }
2390 case AVMEDIA_TYPE_VIDEO:
2391 {
2392 ret = avcodec_parameters_copy(output_stream->codecpar, m_in.m_video.m_stream->codecpar);
2393 if (ret < 0)
2394 {
2395 Logging::error(virtname(), "Could not allocate an encoding context (error '%2').", ffmpeg_geterror(ret).c_str());
2396 return ret;
2397 }
2398
2399 output_stream->time_base = m_in.m_video.m_stream->time_base;
2400
2401#ifdef _DEBUG
2402 print_stream_info(output_stream);
2403#endif // _DEBUG
2404
2405 // Set duration as hint for muxer
2406 output_stream->duration = ffmpeg_rescale_q(m_in.m_video.m_stream->duration, m_in.m_video.m_stream->time_base, output_stream->time_base);
2407
2408 // Save the encoder context for easier access later.
2409 m_out.m_video.set_codec_ctx(nullptr);
2410 // Save the stream index
2411 m_out.m_video.m_stream_idx = output_stream->index;
2412 // Save output video stream for faster reference
2413 m_out.m_video.m_stream = output_stream;
2414
2415 // Update input to output stream map, this is rather boring because currently we only have a single video stream
2417 break;
2418 }
2419 default:
2420 break;
2421 }
2422
2423 output_stream->codecpar->codec_tag = 0;
2424
2425 return 0;
2426}
2427
2428int FFmpeg_Transcoder::add_albumart_stream(const AVCodecContext * input_codec_ctx)
2429{
2430 AVCodecContext * output_codec_ctx = nullptr;
2431 AVStream * output_stream = nullptr;
2432 const AVCodec * input_codec = input_codec_ctx->codec;
2433 const AVCodec * output_codec = nullptr;
2434 AVDictionary * opt = nullptr;
2435 int ret;
2436
2437 // find the encoder
2438 output_codec = avcodec_find_encoder(input_codec->id);
2439 if (output_codec == nullptr)
2440 {
2441 Logging::error(virtname(), "'%1' encoder could not be found.", avcodec_get_name(input_codec->id));
2442 return AVERROR(EINVAL);
2443 }
2444
2445 // Must be a video codec
2446 if (output_codec->type != AVMEDIA_TYPE_VIDEO)
2447 {
2448 Logging::error(virtname(), "INTERNAL TROUBLE! Encoder '%1' is not a video codec.", avcodec_get_name(input_codec->id));
2449 return AVERROR(EINVAL);
2450 }
2451
2452 output_stream = avformat_new_stream(m_out.m_format_ctx, output_codec);
2453 if (output_stream == nullptr)
2454 {
2455 Logging::error(virtname(), "Could not allocate stream for encoder '%1'.", avcodec_get_name(input_codec->id));
2456 return AVERROR(ENOMEM);
2457 }
2458 output_stream->id = static_cast<int>(m_out.m_format_ctx->nb_streams - 1);
2459
2460 output_codec_ctx = avcodec_alloc_context3(output_codec);
2461 if (output_codec_ctx == nullptr)
2462 {
2463 Logging::error(virtname(), "Could not allocate an encoding context.");
2464 return AVERROR(ENOMEM);
2465 }
2466
2467 // Ignore missing width/height when adding album arts
2468#if !IF_DECLARED_CONST
2469 m_out.m_format_ctx->oformat->flags |= AVFMT_NODIMENSIONS;
2470#endif // !IF_DECLARED_CONST
2471 // This is required for some reason (let encoder decide?)
2472 // If not set, write header will fail!
2473 //output_codec_ctx->codec_tag = 0; //av_codec_get_tag(of->codec_tag, codec->codec_id);
2474
2475 //output_stream->codec->framerate = { 1, 0 };
2476
2478 // mp4 album arts do not work with ipod profile. Set mp4.
2479 //if (m_out.m_format_ctx->oformat->mime_type != nullptr && (!strcmp(m_out.m_format_ctx->oformat->mime_type, "application/mp4") || !strcmp(m_out.m_format_ctx->oformat->mime_type, "video/mp4")))
2480 //{
2481 // m_out.m_format_ctx->oformat->name = "mp4";
2482 // m_out.m_format_ctx->oformat->mime_type = "application/mp4";
2483 //}
2484
2485 // copy disposition
2486 // output_stream->disposition = input_stream->disposition;
2487 output_stream->disposition = AV_DISPOSITION_ATTACHED_PIC;
2488
2489 // copy estimated duration as a hint to the muxer
2490 if (output_stream->duration <= 0 && m_in.m_audio.m_stream->duration > 0)
2491 {
2492 output_stream->duration = ffmpeg_rescale_q(m_in.m_audio.m_stream->duration, m_in.m_audio.m_stream->time_base, output_stream->time_base);
2493 }
2494
2495 output_codec_ctx->time_base = { 1, 90000 };
2496 output_stream->time_base = { 1, 90000 };
2497
2498 output_codec_ctx->pix_fmt = input_codec_ctx->pix_fmt;
2499 output_codec_ctx->width = input_codec_ctx->width;
2500 output_codec_ctx->height = input_codec_ctx->height;
2501
2502 // Some formats want stream headers to be separate.
2503 if (m_out.m_format_ctx->oformat->flags & AVFMT_GLOBALHEADER)
2504 {
2505 output_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
2506 }
2507
2508 // Open the encoder for the stream to use it later.
2509 ret = avcodec_open2(output_codec_ctx, output_codec, &opt);
2510 if (ret < 0)
2511 {
2512 Logging::error(virtname(), "Could not open %1 output codec %2 for stream #%3 (error '%4').", get_media_type_string(output_codec->type), get_codec_name(input_codec->id), output_stream->index, ffmpeg_geterror(ret).c_str());
2513 return ret;
2514 }
2515
2516 Logging::debug(virtname(), "Opened album art output codec %1 for stream #%2 (dimensions %3x%4).", get_codec_name(input_codec->id, true), output_stream->index, output_codec_ctx->width, output_codec_ctx->height);
2517
2518 ret = avcodec_parameters_from_context(output_stream->codecpar, output_codec_ctx);
2519 if (ret < 0)
2520 {
2521 Logging::error(virtname(), "Could not initialise stream parameters stream #%1 (error '%2').", output_stream->index, ffmpeg_geterror(ret).c_str());
2522 return ret;
2523 }
2524
2525 StreamRef streamref;
2526
2527 streamref.set_codec_ctx(output_codec_ctx);
2528 streamref.m_stream = output_stream;
2529 streamref.m_stream_idx = output_stream->index;
2530
2531 m_out.m_album_art.push_back(streamref);
2532
2533 return 0;
2534}
2535
2536int FFmpeg_Transcoder::add_albumart_frame(AVStream *output_stream, AVPacket *pkt_in)
2537{
2538 AVPacket *tmp_pkt;
2539 int ret = 0;
2540
2541 tmp_pkt = av_packet_clone(pkt_in);
2542 if (tmp_pkt == nullptr)
2543 {
2544 ret = AVERROR(ENOMEM);
2545 Logging::error(virtname(), "Could not write album art packet (error '%1').", ffmpeg_geterror(ret).c_str());
2546 return ret;
2547 }
2548
2549 Logging::trace(virtname(), "Adding album art stream #%1.", output_stream->index);
2550
2551 tmp_pkt->stream_index = output_stream->index;
2552 tmp_pkt->flags |= AV_PKT_FLAG_KEY; // Contains a single frame, make sure it's a key frame
2553 tmp_pkt->pos = 0;
2554 tmp_pkt->dts = 0;
2555
2556 ret = store_packet(tmp_pkt, AVMEDIA_TYPE_ATTACHMENT);
2557
2558 av_packet_unref(tmp_pkt);
2559
2560 return ret;
2561}
2562
2564{
2566
2567 Logging::debug(virtname(), "Opening output format '%1'.", m_current_format->desttype().c_str());
2568
2569 // Reset active streams
2572
2573 // Check if we can copy audio or video.
2576
2577 // Create a new format context for the output container format.
2578 if (m_current_format->format_name() != "m4a")
2579 {
2580 avformat_alloc_output_context2(&m_out.m_format_ctx, nullptr, m_current_format->format_name().c_str(), nullptr);
2581 }
2582 else
2583 {
2584 avformat_alloc_output_context2(&m_out.m_format_ctx, nullptr, nullptr, ".m4a");
2585 }
2586
2587 if (m_out.m_format_ctx == nullptr)
2588 {
2589 Logging::error(virtname(), "Could not allocate an output format context.");
2590 return AVERROR(ENOMEM);
2591 }
2592
2593 if (!m_is_video)
2594 {
2596 }
2597
2598 //video_codec = m_out.m_format_ctx->oformat->video_codec;
2599
2600 // Open video streams
2601 if (stream_exists(m_in.m_video.m_stream_idx) && m_current_format->video_codec() != AV_CODEC_ID_NONE)
2602 {
2604
2605 if (!m_copy_video)
2606 {
2607 int ret;
2608
2610 if (ret < 0)
2611 {
2612 return ret;
2613 }
2614
2616 {
2617 // Init deinterlace filters
2619 if (ret < 0)
2620 {
2621 return ret;
2622 }
2623 }
2624 }
2625 else
2626 {
2627 int ret;
2628
2629 Logging::info(virtname(), "Copying video stream.");
2630
2631 ret = add_stream_copy(m_current_format->video_codec(), AVMEDIA_TYPE_VIDEO);
2632 if (ret < 0)
2633 {
2634 return ret;
2635 }
2636 }
2637 }
2638
2639 // Open audio streams
2640 if (stream_exists(m_in.m_audio.m_stream_idx) && m_current_format->audio_codec() != AV_CODEC_ID_NONE)
2641 {
2643
2644 if (!m_copy_audio)
2645 {
2646 int ret;
2647
2649 if (ret < 0)
2650 {
2651 return ret;
2652 }
2653 }
2654 else
2655 {
2656 int ret;
2657
2658 Logging::info(virtname(), "Copying audio stream.");
2659
2660 ret = add_stream_copy(m_current_format->audio_codec(), AVMEDIA_TYPE_AUDIO);
2661 if (ret < 0)
2662 {
2663 return ret;
2664 }
2665 }
2666 }
2667
2668 if (stream_exists(m_in.m_video.m_stream_idx) && m_current_format->video_codec() != AV_CODEC_ID_NONE)
2669 {
2670 int ret;
2671
2672 // Open subtitle streams
2673 if (m_in.m_subtitle.size())
2674 {
2675 // No copy option, not worth it for a few frames
2676 // Create as many subtitle streams as required
2677 ret = add_subtitle_streams();
2678 if (ret < 0)
2679 {
2680 return ret;
2681 }
2682 }
2683
2684 // Open streams for external subtitle files
2686 if (ret < 0)
2687 {
2688 return ret;
2689 }
2690 }
2691
2693 {
2694 for (StreamRef & album_art : m_in.m_album_art)
2695 {
2696 int ret;
2697
2698 ret = add_albumart_stream(album_art.m_codec_ctx.get());
2699 if (ret < 0)
2700 {
2701 return ret;
2702 }
2703 }
2704 }
2705
2706 const int buf_size = 5*1024*1024;
2707 unsigned char *iobuffer = static_cast<unsigned char *>(av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE));
2708 if (iobuffer == nullptr)
2709 {
2710 Logging::error(virtname(), "Out of memory opening output file: Unable to allocate I/O buffer.");
2711 return AVERROR(ENOMEM);
2712 }
2713
2714 // open the output file
2715 m_out.m_format_ctx->pb = avio_alloc_context(
2716 iobuffer,
2717 buf_size,
2718 1,
2719 static_cast<void *>(buffer),
2720 nullptr, // read not required
2721 output_write, // write
2722 (m_current_format->audio_codec() != AV_CODEC_ID_OPUS) ? seek : nullptr); // seek
2723
2724 if (m_out.m_format_ctx->pb == nullptr)
2725 {
2726 Logging::error(virtname(), "Out of memory opening output file: Unable to allocate format context.");
2727 return AVERROR(ENOMEM);
2728 }
2729
2730 return 0;
2731}
2732
2734{
2735 for (auto & [key, value] : m_in.m_subtitle)
2736 {
2737 AVCodecID codec_id = m_current_format->subtitle_codec(value.m_stream->codecpar->codec_id); // Get matching output codec
2738
2739 if (codec_id == AV_CODEC_ID_NONE)
2740 {
2741 // No matching output codec
2742 continue;
2743 }
2744
2745 if (map_in_to_out_stream(value.m_stream_idx) != INVALID_STREAM)
2746 {
2747 // Already existing
2748 continue;
2749 }
2750
2751 //m_active_stream_msk |= FFMPEGFS_SUBTITLE;
2752
2753 int ret;
2754
2755 ret = add_subtitle_stream(codec_id, value);
2756 if (ret < 0)
2757 {
2758 return ret;
2759 }
2760 }
2761 return 0;
2762}
2763
2765{
2766 // Fail save: if channel layout not known assume mono or stereo
2767#if LAVU_DEP_OLD_CHANNEL_LAYOUT
2768 if (!m_in.m_audio.m_codec_ctx->ch_layout.nb_channels)
2769 {
2770 av_channel_layout_default(&m_in.m_audio.m_codec_ctx->ch_layout, 2);
2771 }
2772#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2773 if (!m_in.m_audio.m_codec_ctx->channel_layout)
2774 {
2775 m_in.m_audio.m_codec_ctx->channel_layout = static_cast<uint64_t>(av_get_default_channel_layout(m_in.m_audio.m_codec_ctx->channels));
2776 }
2777 if (!m_in.m_audio.m_codec_ctx->channel_layout)
2778 {
2779 m_in.m_audio.m_codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
2780 }
2781#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2782
2783 // Only initialise the resampler if it is necessary, i.e.,
2784 // if and only if the sample formats differ.
2785#if LAVU_DEP_OLD_CHANNEL_LAYOUT
2786 if (m_in.m_audio.m_codec_ctx->sample_fmt == m_out.m_audio.m_codec_ctx->sample_fmt &&
2787 m_in.m_audio.m_codec_ctx->sample_rate == m_out.m_audio.m_codec_ctx->sample_rate &&
2788 !av_channel_layout_compare(&m_in.m_audio.m_codec_ctx->ch_layout, &m_out.m_audio.m_codec_ctx->ch_layout))
2789#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2790 if (m_in.m_audio.m_codec_ctx->sample_fmt == m_out.m_audio.m_codec_ctx->sample_fmt &&
2791 m_in.m_audio.m_codec_ctx->sample_rate == m_out.m_audio.m_codec_ctx->sample_rate &&
2792 m_in.m_audio.m_codec_ctx->channel_layout == m_out.m_audio.m_codec_ctx->channel_layout)
2793#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2794 {
2795 // Formats are same
2797 return 0;
2798 }
2799
2800 if ((m_audio_resample_ctx == nullptr) ||
2801 (m_cur_sample_fmt != m_in.m_audio.m_codec_ctx->sample_fmt) ||
2802 (m_cur_sample_rate != m_in.m_audio.m_codec_ctx->sample_rate) ||
2804 av_channel_layout_compare(&m_cur_ch_layout, &m_in.m_audio.m_codec_ctx->ch_layout))
2805#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2806 (m_cur_channel_layout != m_in.m_audio.m_codec_ctx->channel_layout))
2807#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2808 {
2809 int ret;
2810
2811#if LAVU_DEP_OLD_CHANNEL_LAYOUT
2812 Logging::debug(virtname(), "Creating audio resampler: %1 -> %2 / %3 -> %4 / %5 -> %6.",
2813 get_sample_fmt_name(m_in.m_audio.m_codec_ctx->sample_fmt).c_str(),
2814 get_sample_fmt_name(m_out.m_audio.m_codec_ctx->sample_fmt).c_str(),
2815 format_samplerate(m_in.m_audio.m_codec_ctx->sample_rate).c_str(),
2816 format_samplerate(m_out.m_audio.m_codec_ctx->sample_rate).c_str(),
2817 get_channel_layout_name(&m_in.m_audio.m_codec_ctx->ch_layout).c_str(),
2818 get_channel_layout_name(&m_out.m_audio.m_codec_ctx->ch_layout).c_str());
2819#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2820 Logging::debug(virtname(), "Creating audio resampler: %1 -> %2 / %3 -> %4 / %5 -> %6.",
2821 get_sample_fmt_name(m_in.m_audio.m_codec_ctx->sample_fmt).c_str(),
2822 get_sample_fmt_name(m_out.m_audio.m_codec_ctx->sample_fmt).c_str(),
2823 format_samplerate(m_in.m_audio.m_codec_ctx->sample_rate).c_str(),
2824 format_samplerate(m_out.m_audio.m_codec_ctx->sample_rate).c_str(),
2825 get_channel_layout_name(m_in.m_audio.m_codec_ctx->channels, m_in.m_audio.m_codec_ctx->channel_layout).c_str(),
2826 get_channel_layout_name(m_out.m_audio.m_codec_ctx->channels, m_out.m_audio.m_codec_ctx->channel_layout).c_str());
2827#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2828
2830
2833#if LAVU_DEP_OLD_CHANNEL_LAYOUT
2834 av_channel_layout_copy(&m_cur_ch_layout, &m_in.m_audio.m_codec_ctx->ch_layout);
2835#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2836 m_cur_channel_layout = m_in.m_audio.m_codec_ctx->channel_layout;
2837#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
2838
2839 // Create a resampler context for the conversion.
2840 // Set the conversion parameters.
2841#if SWR_DEP_ALLOC_SET_OPTS
2842 ret = swr_alloc_set_opts2(&m_audio_resample_ctx,
2843 &m_out.m_audio.m_codec_ctx->ch_layout,
2844 m_out.m_audio.m_codec_ctx->sample_fmt,
2845 m_out.m_audio.m_codec_ctx->sample_rate,
2846 &m_in.m_audio.m_codec_ctx->ch_layout,
2847 m_in.m_audio.m_codec_ctx->sample_fmt,
2848 m_in.m_audio.m_codec_ctx->sample_rate,
2849 0, nullptr);
2850 if (ret < 0)
2851 {
2852 Logging::error(virtname(), "Could not allocate resample context (error '%1').", ffmpeg_geterror(ret).c_str());
2853 return ret;
2854 }
2855#else
2856 m_audio_resample_ctx = swr_alloc_set_opts(nullptr,
2857 static_cast<int64_t>(m_out.m_audio.m_codec_ctx->channel_layout),
2858 m_out.m_audio.m_codec_ctx->sample_fmt,
2859 m_out.m_audio.m_codec_ctx->sample_rate,
2860 static_cast<int64_t>(m_in.m_audio.m_codec_ctx->channel_layout),
2861 m_in.m_audio.m_codec_ctx->sample_fmt,
2862 m_in.m_audio.m_codec_ctx->sample_rate,
2863 0, nullptr);
2864 if (m_audio_resample_ctx == nullptr)
2865 {
2866 Logging::error(virtname(), "Could not allocate a resample context.");
2867 return AVERROR(ENOMEM);
2868 }
2869#endif
2870
2871 // Open the resampler with the specified parameters.
2872 ret = swr_init(m_audio_resample_ctx);
2873 if (ret < 0)
2874 {
2875 Logging::error(virtname(), "Could not open resampler context (error '%1').", ffmpeg_geterror(ret).c_str());
2876 swr_free(&m_audio_resample_ctx);
2877 m_audio_resample_ctx = nullptr;
2878 return ret;
2879 }
2880 }
2881 return 0;
2882}
2883
2885{
2886 // Create the audio FIFO buffer based on the specified output sample format.
2887 m_audio_fifo = av_audio_fifo_alloc(m_out.m_audio.m_codec_ctx->sample_fmt, get_channels(m_out.m_audio.m_codec_ctx.get()), 1);
2888 if (m_audio_fifo == nullptr)
2889 {
2890 Logging::error(virtname(), "Could not allocate an audio FIFO.");
2891 return AVERROR(ENOMEM);
2892 }
2893 return 0;
2894}
2895
2896int FFmpeg_Transcoder::update_format(AVDictionary** dict, const PROFILE_OPTION_VEC &option_vec) const
2897{
2898 int ret = 0;
2899
2900 for (const PROFILE_OPTION & option : option_vec)
2901 {
2902 if ((option.m_options & OPT_AUDIO) && stream_exists(m_out.m_video.m_stream_idx))
2903 {
2904 // Option for audio only, but file contains video stream
2905 continue;
2906 }
2907
2908 if ((option.m_options & OPT_VIDEO) && !stream_exists(m_out.m_video.m_stream_idx))
2909 {
2910 // Option for video, but file contains no video stream
2911 continue;
2912 }
2913
2914 Logging::trace(virtname(), "Profile format option -%1%2%3.", option.m_key, *option.m_value ? " " : "", option.m_value);
2915
2916 ret = dict_set_with_check(dict, option.m_key, option.m_value, option.m_flags, virtname());
2917 if (ret < 0)
2918 {
2919 break;
2920 }
2921 }
2922 return ret;
2923}
2924
2925int FFmpeg_Transcoder::prepare_format(AVDictionary** dict, FILETYPE filetype) const
2926{
2927 int ret = 0;
2928
2929 for (const PROFILE_LIST & profile : m_profile)
2930 {
2931 if (profile.m_filetype == filetype && profile.m_profile == params.m_profile)
2932 {
2933 ret = update_format(dict, profile.m_option_format);
2934 break;
2935 }
2936 }
2937
2938 if (filetype == FILETYPE::MP4 || filetype == FILETYPE::PRORES || filetype == FILETYPE::TS || filetype == FILETYPE::HLS)
2939 {
2940 // All
2941 dict_set_with_check(dict, "flags:a", "+global_header", 0, virtname());
2942 dict_set_with_check(dict, "flags:v", "+global_header", 0, virtname());
2943 }
2944
2945 return ret;
2946}
2947
2949{
2950 // Insert fake WAV header (fill in size fields with estimated values instead of setting to -1)
2951 AVIOContext * output_io_context = static_cast<AVIOContext *>(m_out.m_format_ctx->pb);
2952 Buffer *buffer = static_cast<Buffer *>(output_io_context->opaque);
2953 size_t current_offset = buffer->tell();
2954 size_t read_offset = 0;
2955 WAV_HEADER wav_header;
2956 WAV_LIST_HEADER list_header;
2957 WAV_DATA_HEADER data_header;
2958
2959 buffer->copy(reinterpret_cast<uint8_t*>(&wav_header), 0, sizeof(WAV_HEADER));
2960 read_offset = sizeof(WAV_HEADER);
2961
2962 if (wav_header.m_audio_format == 0xfffe)
2963 {
2964 //WAV_HEADER_EX wav_header_ex;
2965 WAV_FACT wav_fact;
2966
2967 //buffer->copy(reinterpret_cast<uint8_t*>(&wav_header_ex), read_offset, sizeof(WAV_HEADER_EX));
2968 read_offset += sizeof(WAV_HEADER_EX); // Need to skip extension header
2969
2970 // Check for presence of "fact" chunk
2971 buffer->copy(reinterpret_cast<uint8_t*>(&wav_fact), read_offset, sizeof(WAV_FACT));
2972 if (!memcmp(&wav_fact.m_chunk_id, "fact", sizeof(wav_fact.m_chunk_id)))
2973 {
2974 read_offset += sizeof(WAV_FACT); // Also skip fact header
2975 }
2976 }
2977
2978 // Read list header
2979 buffer->copy(reinterpret_cast<uint8_t*>(&list_header), read_offset, sizeof(WAV_LIST_HEADER));
2980 read_offset += sizeof(WAV_LIST_HEADER) + list_header.m_data_bytes - 4;
2981 // Read data header
2982 buffer->copy(reinterpret_cast<uint8_t*>(&data_header), read_offset, sizeof(WAV_DATA_HEADER));
2983
2984 // Fill in size fields with predicted size
2985 wav_header.m_wav_size = static_cast<unsigned int>(predicted_filesize() - 8);
2986 data_header.m_data_bytes = static_cast<unsigned int>(predicted_filesize() - (read_offset + sizeof(WAV_DATA_HEADER)));
2987#if __BYTE_ORDER == __BIG_ENDIAN
2988 wav_header.m_wav_size = __builtin_bswap32(wav_header.m_wav_size);
2989 data_header.m_data_bytes = __builtin_bswap32(data_header.m_data_bytes);
2990#endif
2991
2992 // Write updated wav header
2993 buffer->seek(0, SEEK_SET);
2994 buffer->writeio(reinterpret_cast<uint8_t*>(&wav_header), sizeof(WAV_HEADER));
2995
2996 // Write updated data header
2997 buffer->seek(static_cast<long>(read_offset), SEEK_SET);
2998 buffer->writeio(reinterpret_cast<uint8_t*>(&data_header), sizeof(WAV_DATA_HEADER));
2999
3000 // Restore write position
3001 buffer->seek(static_cast<long>(current_offset), SEEK_SET);
3002
3003 return 0;
3004}
3005
3006int FFmpeg_Transcoder::read_aiff_chunk(Buffer *buffer, size_t *buffoffset, const char *ID, uint8_t *chunk, size_t *size) const
3007{
3008 AIFF_CHUNK *p = reinterpret_cast<AIFF_CHUNK*>(chunk);
3009 size_t buffsize = *size;
3010
3011 for (;;)
3012 {
3013 if (!buffer->copy(chunk, *buffoffset, buffsize))
3014 {
3015 return -1;
3016 }
3017
3018 if (buffer->eof())
3019 {
3020 errno = 0;
3021 return -1;
3022 }
3023
3024 if (!memcmp(&p->m_ckID, AIFF_FORMID, sizeof(p->m_ckID)))
3025 {
3026 // Special case: FormChunk has a fixed size
3027 *size = sizeof(AIFF_FORMCHUNK);
3028 }
3029 else
3030 {
3031#if __BYTE_ORDER == __BIG_ENDIAN
3032 *size = p->m_ckSize + 8;
3033#else
3034 *size = __builtin_bswap32(p->m_ckSize) + 8;
3035#endif
3036 }
3037
3038 if (!memcmp(&p->m_ckID, ID, sizeof(p->m_ckID)))
3039 {
3040 // Found
3041 break;
3042 }
3043
3044 // Advance to next potential position
3045 *buffoffset += *size;
3046 }
3047
3048 return 0;
3049}
3050
3052{
3053 // Insert fake WAV header (fill in size fields with estimated values instead of setting to -1)
3054 AVIOContext * output_io_context = static_cast<AVIOContext *>(m_out.m_format_ctx->pb);
3055 Buffer *buffer = static_cast<Buffer *>(output_io_context->opaque);
3056 size_t current_offset = buffer->tell();
3057 size_t read_offset = 0;
3058 size_t size;
3059 AIFF_FORMCHUNK form_chunk;
3060 AIFF_COMMONCHUNK common_chunk;
3061
3062 size = sizeof(form_chunk);
3063 if (read_aiff_chunk(buffer, &read_offset, AIFF_FORMID, reinterpret_cast<uint8_t*>(&form_chunk), &size))
3064 {
3065 return -1;
3066 }
3067
3068 read_offset += size;
3069
3070 form_chunk.m_ckSize = static_cast<uint32_t>(predicted_filesize() - 8);
3071#if __BYTE_ORDER != __BIG_ENDIAN
3072 form_chunk.m_ckSize = __builtin_bswap32(form_chunk.m_ckSize);
3073#endif
3074
3075 size = sizeof(common_chunk);
3076 if (read_aiff_chunk(buffer, &read_offset, AIFF_COMMONID, reinterpret_cast<uint8_t*>(&common_chunk), &size))
3077 {
3078 return -1;
3079 }
3080
3081 read_offset += size;
3082
3083 AIFF_SOUNDDATACHUNK sounddata_chunk;
3084
3085 size = sizeof(sounddata_chunk);
3086 if (read_aiff_chunk(buffer, &read_offset, AIFF_SOUNDATAID, reinterpret_cast<uint8_t*>(&sounddata_chunk), &size))
3087 {
3088 return -1;
3089 }
3090
3091 sounddata_chunk.m_ckSize = static_cast<uint32_t>(predicted_filesize() - read_offset);
3092#if __BYTE_ORDER != __BIG_ENDIAN
3093 sounddata_chunk.m_ckSize = __builtin_bswap32(sounddata_chunk.m_ckSize);
3094#endif
3095
3096 // Write updated AIFF header
3097 buffer->seek(0, SEEK_SET);
3098 buffer->writeio(reinterpret_cast<uint8_t*>(&form_chunk), sizeof(form_chunk));
3099
3100 // Write updated data header
3101 buffer->seek(static_cast<long>(read_offset), SEEK_SET);
3102 buffer->writeio(reinterpret_cast<uint8_t*>(&sounddata_chunk), sizeof(sounddata_chunk));
3103
3104 // Restore write position
3105 buffer->seek(static_cast<long>(current_offset), SEEK_SET);
3106
3107 return 0;
3108}
3109
3111{
3112 AVDictionary* dict = nullptr;
3113 int ret;
3114
3115 ret = prepare_format(&dict, m_out.m_filetype);
3116 if (ret < 0)
3117 {
3118 return ret;
3119 }
3120
3121 ret = avformat_write_header(m_out.m_format_ctx, &dict);
3122 if (ret < 0)
3123 {
3124 Logging::error(virtname(), "Could not write output file header (error '%1').", ffmpeg_geterror(ret).c_str());
3125 return ret;
3126 }
3127
3128 switch (m_current_format->filetype())
3129 {
3130 case FILETYPE::WAV:
3131 {
3132 ret = create_fake_wav_header();
3133 break;
3134 }
3135 case FILETYPE::AIFF:
3136 {
3138 break;
3139 }
3140 default:
3141 {
3142 break;
3143 }
3144 }
3145
3146 return ret;
3147}
3148
3149int FFmpeg_Transcoder::alloc_picture(AVFrame *frame, AVPixelFormat pix_fmt, int width, int height) const
3150{
3151 int ret;
3152
3153 frame->format = pix_fmt;
3154 frame->width = width;
3155 frame->height = height;
3156
3157 // allocate the buffers for the frame data
3158 ret = av_frame_get_buffer(frame, 32);
3159 if (ret < 0)
3160 {
3161 Logging::error(virtname(), "Could not allocate frame data (error '%1').", ffmpeg_geterror(ret).c_str());
3162 return ret;
3163 }
3164
3165 return 0;
3166}
3167
3168int FFmpeg_Transcoder::decode(AVCodecContext *codec_ctx, AVFrame *frame, int *got_frame, const AVPacket *pkt) const
3169{
3170 int ret;
3171
3172 *got_frame = 0;
3173
3174 if (pkt != nullptr)
3175 {
3176 ret = avcodec_send_packet(codec_ctx, pkt);
3177 if (ret < 0 && ret != AVERROR_EOF)
3178 {
3179 // In particular, we don't expect AVERROR(EAGAIN), because we read all
3180 // decoded frames with avcodec_receive_frame() until done, so this should be handled
3181 // as an error.
3182 if (ret == AVERROR(EAGAIN))
3183 {
3184 ret = AVERROR_EXTERNAL;
3185 }
3186
3187 if (is_audio_stream(pkt->stream_index) && stream_exists(m_out.m_audio.m_stream_idx))
3188 {
3189 Logging::error(filename(), "Could not send audio packet at PTS=%1 to decoder (error '%2').", ffmpeg_rescale_q(pkt->pts, m_in.m_audio.m_stream->time_base), ffmpeg_geterror(ret).c_str());
3190 }
3191 else if (is_video_stream(pkt->stream_index) && stream_exists(m_out.m_video.m_stream_idx))
3192 {
3193 Logging::error(filename(), "Could not send video packet at PTS=%1 to decoder (error '%2').", ffmpeg_rescale_q(pkt->pts, m_in.m_video.m_stream->time_base), ffmpeg_geterror(ret).c_str());
3194 }
3195 else
3196 {
3197 // Should never come here, but what the heck...
3198 Logging::error(filename(), "Could not send packet at PTS=%1 to decoder (error '%2').", pkt->pts, ffmpeg_geterror(ret).c_str());
3199 }
3200 return ret;
3201 }
3202 }
3203
3204 ret = avcodec_receive_frame(codec_ctx, frame);
3205 if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
3206 {
3207 Logging::error(filename(), "Could not receive packet from decoder (error '%1').", ffmpeg_geterror(ret).c_str());
3208 }
3209
3217 *got_frame = (ret >= 0) ? 1 : 0;
3218
3219 return ret;
3220}
3221
3222int FFmpeg_Transcoder::decode_audio_frame(AVPacket *pkt, int *decoded)
3223{
3224 int data_present = 0;
3225 int ret = 0;
3226
3227 *decoded = 0;
3228
3229 // Decode the audio frame stored in the temporary packet.
3230 // The input audio stream decoder is used to do this.
3231 // If we are at the end of the file, pass an empty packet to the decoder
3232 // to flush it.
3233
3234 // Since FFMpeg version >= 3.2 this is deprecated
3235 bool again = false;
3236
3237 data_present = 0;
3238
3239 // read all the output frames (in general there may be any number of them)
3240 while (ret >= 0)
3241 {
3243
3244 ret = frame.res();
3245 if (ret < 0)
3246 {
3247 Logging::error(filename(), "Could not decode audio frame (error '%1').", ffmpeg_geterror(ret).c_str());
3248 break;
3249 }
3250
3251 ret = decode(m_in.m_audio.m_codec_ctx.get(), frame, &data_present, again ? nullptr : pkt);
3252 if (!data_present)
3253 {
3254 break;
3255 }
3256
3257 if (ret < 0)
3258 {
3259 // Anything else is an error, report it!
3260 Logging::error(filename(), "Could not decode audio frame (error '%1').", ffmpeg_geterror(ret).c_str());
3261 break;
3262 }
3263
3264 again = true;
3265
3266 *decoded += pkt->size;
3267
3268 // If there is decoded data, convert and store it
3269 if (frame->nb_samples)
3270 {
3271 // Temporary storage for the converted input samples.
3272 uint8_t **converted_input_samples = nullptr;
3273 try
3274 {
3275 int nb_output_samples;
3276
3277 // Initialise the resampler to be able to convert audio sample formats.
3278 ret = init_resampler();
3279 if (ret)
3280 {
3281 throw ret;
3282 }
3283
3284 nb_output_samples = (m_audio_resample_ctx != nullptr) ? swr_get_out_samples(m_audio_resample_ctx, frame->nb_samples) : frame->nb_samples;
3285
3286 // Store audio frame
3287 // Initialise the temporary storage for the converted input samples.
3288 ret = init_converted_samples(&converted_input_samples, nb_output_samples);
3289 if (ret < 0)
3290 {
3291 throw ret;
3292 }
3293
3294 // Convert the input samples to the desired output sample format.
3295 // This requires a temporary storage provided by converted_input_samples.
3296 ret = convert_samples(frame->extended_data, frame->nb_samples, converted_input_samples, &nb_output_samples);
3297 if (ret < 0)
3298 {
3299 throw ret;
3300 }
3301
3302 // Add the converted input samples to the audio FIFO buffer for later processing.
3303 ret = add_samples_to_fifo(converted_input_samples, nb_output_samples);
3304 if (ret < 0)
3305 {
3306 throw ret;
3307 }
3308 ret = 0;
3309 }
3310 catch (int _ret)
3311 {
3312 ret = _ret;
3313 }
3314
3315 if (converted_input_samples != nullptr)
3316 {
3317 av_freep(&converted_input_samples[0]);
3318 av_free(converted_input_samples);
3319 }
3320 }
3321 }
3322 return ret;
3323}
3324
3325int FFmpeg_Transcoder::decode_video_frame(AVPacket *pkt, int *decoded)
3326{
3327 int data_present;
3328 int ret = 0;
3329
3330 *decoded = 0;
3331
3332 // NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
3333 // and this is the only method to use them because you cannot
3334 // know the compressed data size before analysing it.
3335
3336 // BUT some other codecs (msmpeg4, mpeg4) are inherently frame
3337 // based, so you must call them with all the data for one
3338 // frame exactly. You must also initialise 'width' and
3339 // 'height' before initialising them.
3340
3341 // NOTE2: some codecs allow the raw parameters (frame size,
3342 // sample rate) to be changed at any frame. We handle this, so
3343 // you should also take care of it
3344
3345 // Since FFMpeg version >= 3.2 this is deprecated
3346 bool again = false;
3347
3348 data_present = 0;
3349
3350 // read all the output frames (in general there may be any number of them)
3351 while (ret >= 0)
3352 {
3354
3355 ret = frame.res();
3356 if (ret < 0)
3357 {
3358 Logging::error(filename(), "Could not decode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
3359 break;
3360 }
3361
3362 ret = decode(m_in.m_video.m_codec_ctx.get(), frame, &data_present, again ? nullptr : pkt);
3363 if (!data_present)
3364 {
3365 // No data available
3366 break;
3367 }
3368
3369 if (ret < 0)
3370 {
3371 // Anything else is an error, report it!
3372 Logging::error(filename(), "Could not decode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
3373 break;
3374 }
3375
3376 if (m_hwaccel_enable_dec_buffering && frame != nullptr)
3377 {
3379
3380 ret = sw_frame.res();
3381 if (ret < 0)
3382 {
3383 Logging::error(filename(), "Could not decode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
3384 return ret;
3385 }
3386
3387 // If decoding is done in hardware, the resulting frame data needs to be copied to software memory
3388 //ret = hwframe_copy_from_hw(m_in.m_video.m_codec_ctx.get(), &sw_frame, frame);
3389
3390 // retrieve data from GPU to CPU
3391 ret = av_hwframe_transfer_data(sw_frame, frame, 0); // hwframe_copy_from_hw
3392 if (ret < 0)
3393 {
3394 Logging::error(filename(), "Error transferring the data to system memory (error '%1').", ffmpeg_geterror(ret).c_str());
3395 break;
3396 }
3397 frame = sw_frame;
3398 }
3399
3400 again = true;
3401 *decoded += pkt->size;
3402
3403 // Sometimes only a few packets contain valid dts/pts/pos data, so we keep it
3404 if (pkt->dts != AV_NOPTS_VALUE)
3405 {
3406 int64_t pkt_dts = pkt->dts;
3407 if (pkt_dts > m_pts)
3408 {
3409 m_pts = pkt_dts;
3410 }
3411 }
3412 else if (pkt->pts != AV_NOPTS_VALUE)
3413 {
3414 int64_t pkt_pts = pkt->pts;
3415 if (pkt_pts > m_pts)
3416 {
3417 m_pts = pkt_pts;
3418 }
3419 }
3420
3421 if (pkt->pos > -1)
3422 {
3423 m_pos = pkt->pos;
3424 }
3425
3426 if (frame != nullptr)
3427 {
3428 if (!(frame->flags & AV_FRAME_FLAG_CORRUPT || frame->flags & AV_FRAME_FLAG_DISCARD))
3429 {
3430 ret = send_filters(&frame, ret);
3431 if (ret)
3432 {
3433 return ret;
3434 }
3435
3436 if (m_sws_ctx != nullptr)
3437 {
3439
3440 ret = tmp_frame.res();
3441 if (ret < 0)
3442 {
3443 Logging::error(filename(), "Could not decode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
3444 return ret;
3445 }
3446
3447 AVCodecContext *output_codec_ctx = m_out.m_video.m_codec_ctx.get();
3448
3449 ret = alloc_picture(tmp_frame, m_out.m_pix_fmt, output_codec_ctx->width, output_codec_ctx->height);
3450 if (ret < 0)
3451 {
3452 return ret;
3453 }
3454
3455 sws_scale(m_sws_ctx,
3456 static_cast<const uint8_t * const *>(frame->data), frame->linesize,
3457 0, frame->height,
3458 tmp_frame->data, tmp_frame->linesize);
3459
3460 tmp_frame->pts = frame->pts;
3461 tmp_frame->best_effort_timestamp = frame->best_effort_timestamp;
3462
3463 frame = tmp_frame;
3464 }
3465
3466 int64_t best_effort_timestamp = frame->best_effort_timestamp;
3467
3468 if (best_effort_timestamp != AV_NOPTS_VALUE)
3469 {
3470 frame->pts = best_effort_timestamp;
3471 }
3472
3473 if (frame->pts == AV_NOPTS_VALUE)
3474 {
3475 frame->pts = m_pts;
3476 }
3477
3478 int64_t video_start_time = m_out.m_video.m_start_time;
3479
3480 if (m_out.m_video.m_stream != nullptr && frame->pts != AV_NOPTS_VALUE)
3481 {
3482 if (m_in.m_video.m_stream->time_base.den != m_out.m_video.m_stream->time_base.den || m_in.m_video.m_stream->time_base.num != m_out.m_video.m_stream->time_base.num)
3483 {
3484 frame->pts = ffmpeg_rescale_q_rnd(frame->pts, m_in.m_video.m_stream->time_base, m_out.m_video.m_stream->time_base);
3485 video_start_time = ffmpeg_rescale_q_rnd(video_start_time, m_in.m_video.m_stream->time_base, m_out.m_video.m_stream->time_base);
3486 }
3487
3488 // Fix for issue #46: bitrate too high.
3489 // Solution found here https://stackoverflow.com/questions/11466184/setting-video-bit-rate-through-ffmpeg-api-is-ignored-for-libx264-codec
3490 // This is permanently used in the current ffmpeg.c code (see commit: e3fb9af6f1353f30855eaa1cbd5befaf06e303b8 Date:Wed Jan 22 15:52:10 2020 +0100)
3491 frame->pts = ffmpeg_rescale_q_rnd(frame->pts, m_out.m_video.m_stream->time_base, m_out.m_video.m_codec_ctx->time_base);
3492 video_start_time = ffmpeg_rescale_q_rnd(video_start_time, m_out.m_video.m_stream->time_base, m_out.m_video.m_codec_ctx->time_base);
3493 }
3494
3495 frame->quality = m_out.m_video.m_codec_ctx->global_quality;
3496#if !LAVU_ADD_NEW_FRAME_FLAGS
3497 frame->key_frame = 0; // Leave that decision to encoder
3498#endif
3499 frame->pict_type = AV_PICTURE_TYPE_NONE; // other than AV_PICTURE_TYPE_NONE causes warnings
3500
3501 if (frame->pts != AV_NOPTS_VALUE)
3502 {
3503 int64_t tmp_pts = frame->pts - video_start_time;
3504 int64_t pos = ffmpeg_rescale_q_rnd(tmp_pts, m_out.m_video.m_codec_ctx->time_base);
3505 if (pos < 0)
3506 {
3507 pos = 0;
3508 }
3509
3510 if (is_hls())
3511 {
3512 // Issue #90: Insert key frame at start of each subsequent HLS segment
3513 uint32_t next_segment = get_next_segment(pos);
3514
3515 if (goto_next_segment(next_segment) && !m_insert_keyframe)
3516 {
3517 Logging::debug(virtname(), "Force key frame for next segment no. %1 at PTS=%2 (%3).", next_segment, tmp_pts, format_duration(pos).c_str());
3518
3519#if LAVU_ADD_NEW_FRAME_FLAGS
3520 frame->flags |= AV_FRAME_FLAG_KEY; // This is required to reset the GOP counter (insert the next key frame after gop_size frames)
3521#else // !LAVU_ADD_NEW_FRAME_FLAGS
3522 frame->key_frame = 1; // This is required to reset the GOP counter (insert the next key frame after gop_size frames)
3523#endif // !LAVU_ADD_NEW_FRAME_FLAGS
3524 frame->pict_type = AV_PICTURE_TYPE_I;
3525 m_insert_keyframe = true;
3526 }
3527 }
3528
3529 m_frame_map.insert(std::make_pair(pos, frame));
3530 }
3531 else
3532 {
3533 m_frame_map.insert(std::make_pair(0, frame));
3534 }
3535 }
3536 }
3537 }
3538
3539 return ret;
3540}
3541
3542int FFmpeg_Transcoder::decode_subtitle(AVPacket *pkt, int *decoded)
3543{
3544 StreamRef_map::const_iterator it = m_in.m_subtitle.find(pkt->stream_index);
3545
3546 *decoded = 0;
3547
3548 if (it == m_in.m_subtitle.cend())
3549 {
3550 // Should never happen, this should never be called with anything else than subtitle packets.
3551 int ret = AVERROR_STREAM_NOT_FOUND;
3552 Logging::error(filename(), "INTERNAL ERROR: FFmpeg_Transcoder::decode_subtitle()! Subtitle stream #%1 not found (error '%2').", ffmpeg_geterror(ret).c_str());
3553 return ret;
3554 }
3555
3556 // Decode the audio frame stored in the temporary packet.
3557 // The input audio stream decoder is used to do this.
3558 // If we are at the end of the file, pass an empty packet to the decoder
3559 // to flush it.
3560
3561 // Temporary storage of the input samples of the frame read from the file.
3562
3563 int out_stream_idx = map_in_to_out_stream(it->first);
3564
3565 if (out_stream_idx == INVALID_STREAM)
3566 {
3567 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::decode_subtitle()! Unable to map input subtitle stream #%1 to output stream.", it->first);
3568 throw AVERROR(EINVAL);
3569 }
3570
3571 return decode_subtitle(it->second.m_codec_ctx.get(), pkt, decoded, out_stream_idx);
3572}
3573
3574int FFmpeg_Transcoder::decode_subtitle(AVCodecContext *codec_ctx, AVPacket *pkt, int *decoded, int out_stream_idx)
3575{
3576 FFmpeg_Subtitle subtitle(out_stream_idx);
3577 int data_present = 0;
3578 int ret = 0;
3579
3580 *decoded = 0;
3581
3582 ret = subtitle.res();
3583 if (ret < 0)
3584 {
3585 Logging::error(filename(), "Could not decode subtitle (error '%1').", ffmpeg_geterror(ret).c_str());
3586 return ret;
3587 }
3588
3589 ret = avcodec_decode_subtitle2(codec_ctx, subtitle, &data_present, pkt);
3590
3591 if (ret < 0 && ret != AVERROR(EINVAL))
3592 {
3593 Logging::error(filename(), "Could not decode subtitle frame (error '%1').", ffmpeg_geterror(ret).c_str());
3594 data_present = 0;
3595 }
3596 else
3597 {
3598 *decoded = ret;
3599 ret = 0;
3600 }
3601
3602 if (data_present)
3603 {
3604 // If there is decoded data, store it
3605 // sub->pts is already in AV_TIME_BASE
3606 m_frame_map.insert(std::make_pair(subtitle->pts, subtitle));
3607 }
3608
3609 return ret;
3610}
3611
3612int FFmpeg_Transcoder::store_packet(AVPacket *pkt, AVMediaType mediatype)
3613{
3614 if (is_hls() && pkt->pts != AV_NOPTS_VALUE)
3615 {
3616 switch (mediatype)
3617 {
3618 case AVMEDIA_TYPE_AUDIO:
3619 {
3620 int64_t pos = ffmpeg_rescale_q_rnd(pkt->pts - m_out.m_audio.m_start_time, m_out.m_audio.m_stream->time_base);
3621 if (pos < 0)
3622 {
3623 pos = 0;
3624 }
3625 uint32_t next_segment = get_next_segment(pos);
3626
3627 if (goto_next_segment(next_segment))
3628 {
3630 {
3632
3633 Logging::trace(virtname(), "Buffering audio packets until the next segment no. %1 from position %2 (%3).", next_segment, pos, format_duration(pos).c_str());
3634 }
3635
3636 m_hls_packet_fifo.push(av_packet_clone(pkt));
3637 return 0;
3638 }
3639 break;
3640 }
3641 case AVMEDIA_TYPE_VIDEO:
3642 {
3643 int64_t pos = ffmpeg_rescale_q_rnd(pkt->pts - m_out.m_video.m_start_time, m_out.m_video.m_stream->time_base);
3644 if (pos < 0)
3645 {
3646 pos = 0;
3647 }
3648 uint32_t next_segment = get_next_segment(pos);
3649
3650 if (goto_next_segment(next_segment))
3651 {
3653 {
3655
3656 Logging::trace(virtname(), "Buffering video packets until the next segment no. %1 from position %2 (%3).", next_segment, pos, format_duration(pos).c_str());
3657 }
3658
3659 m_hls_packet_fifo.push(av_packet_clone(pkt));
3660 return 0;
3661 }
3662 break;
3663 }
3664 case AVMEDIA_TYPE_SUBTITLE:
3665 {
3666 StreamRef * subtitle = get_out_subtitle_stream(pkt->stream_index);
3667
3668 if (subtitle != nullptr && subtitle->m_stream != nullptr)
3669 {
3670 int64_t pos = ffmpeg_rescale_q_rnd(pkt->pts - subtitle->m_start_time, subtitle->m_stream->time_base);
3671 if (pos < 0)
3672 {
3673 pos = 0;
3674 }
3675 uint32_t next_segment = get_next_segment(pos);
3676
3677 if (goto_next_segment(next_segment))
3678 {
3679 m_hls_packet_fifo.push(av_packet_clone(pkt));
3680 return 0;
3681 }
3682 }
3683 break;
3684 }
3685 default:
3686 {
3687 break;
3688 }
3689 }
3690 }
3691
3692 int ret = av_write_frame(m_out.m_format_ctx, pkt);
3693
3694 if (ret < 0)
3695 {
3696 const char *type;
3697
3698 if (mediatype != AVMEDIA_TYPE_ATTACHMENT)
3699 {
3700 type = av_get_media_type_string(mediatype);
3701
3702 if (type == nullptr)
3703 {
3704 type = "unknown";
3705 }
3706 }
3707 else
3708 {
3709 type = "album art";
3710 }
3711
3712 Logging::error(virtname(), "Could not write %1 frame (error '%2').", type, ffmpeg_geterror(ret).c_str());
3713 }
3714
3715 return ret;
3716}
3717
3718void FFmpeg_Transcoder::make_pts(AVPacket *pkt, int64_t *cur_ts) const
3719{
3720 if (pkt->pts != AV_NOPTS_VALUE)
3721 {
3722 *cur_ts = pkt->pts + pkt->duration;
3723 }
3724 else if (pkt->dts != AV_NOPTS_VALUE)
3725 {
3726 *cur_ts = pkt->dts;
3727 }
3728
3729 if (pkt->duration)
3730 {
3731 if (pkt->pts == AV_NOPTS_VALUE)
3732 {
3733 pkt->pts = *cur_ts;
3734 }
3735
3736 *cur_ts += pkt->duration;
3737
3738 if (pkt->dts == AV_NOPTS_VALUE)
3739 {
3740 pkt->dts = *cur_ts;
3741 }
3742 }
3743}
3744
3746{
3747 int ret = 0;
3748
3749 if (m_in.m_audio.m_stream != nullptr && is_audio_stream(pkt->stream_index) && stream_exists(m_out.m_audio.m_stream_idx))
3750 {
3751 if (m_reset_pts & FFMPEGFS_AUDIO && pkt->pts != AV_NOPTS_VALUE)
3752 {
3753 m_reset_pts &= ~FFMPEGFS_AUDIO; // Clear reset bit
3754
3755 int64_t pkt_pts = ffmpeg_rescale_q(pkt->pts, m_in.m_audio.m_stream->time_base);
3756
3757 m_out.m_audio_pts = ffmpeg_rescale_q(pkt_pts, av_get_time_base_q(), m_out.m_audio.m_stream->time_base);
3758
3759 Logging::debug(virtname(), "Reset the PTS from the audio packet to %1.", format_duration(pkt_pts).c_str());
3760 }
3761
3762 if (!m_copy_audio)
3763 {
3764 int decoded = 0;
3765 ret = decode_audio_frame(pkt, &decoded);
3766 }
3767 else
3768 {
3769 // Simply copy packet without recoding
3770 pkt->stream_index = m_out.m_audio.m_stream_idx;
3771
3772 // Rescale packet
3773 av_packet_rescale_ts(pkt, m_in.m_audio.m_stream->time_base, m_out.m_audio.m_stream->time_base);
3774
3775 // Make PTS/DTS if missing
3776 make_pts(pkt, &m_cur_audio_ts);
3777
3778 pkt->pos = -1;
3779
3780 ret = store_packet(pkt, AVMEDIA_TYPE_AUDIO);
3781 }
3782 }
3783 else if (m_in.m_video.m_stream != nullptr && is_video_stream(pkt->stream_index) && (stream_exists(m_out.m_video.m_stream_idx) || is_frameset()))
3784 {
3785 if (m_reset_pts & FFMPEGFS_VIDEO && pkt->pts != AV_NOPTS_VALUE)
3786 {
3787 m_reset_pts &= ~FFMPEGFS_VIDEO; // Clear reset bit
3788
3789 int64_t pkt_pts = ffmpeg_rescale_q(pkt->pts, m_in.m_video.m_stream->time_base);
3790
3791 m_out.m_video_pts = ffmpeg_rescale_q(pkt_pts, av_get_time_base_q(), m_out.m_video.m_stream->time_base);
3792
3793 Logging::debug(virtname(), "Reset PTS from the video packet to %1.", format_duration(pkt_pts).c_str());
3794 }
3795
3796 if (!m_copy_video)
3797 {
3798 int decoded = 0;
3809#ifndef USE_LIBDVD
3810 ret = decode_video_frame(pkt, &decoded);
3811#else //USE_LIBDVD
3813 {
3814 ret = decode_video_frame(pkt, &decoded);
3815 }
3816 else
3817 {
3818 int lastret = 0;
3819
3820 do
3821 {
3822 // Decode one frame.
3823 ret = decode_video_frame(pkt, &decoded);
3824
3825 if ((ret == AVERROR(EAGAIN) && ret == lastret) || ret == AVERROR_EOF)
3826 {
3827 // If EAGAIN reported twice or stream at EOF
3828 // quit loop, but this is not an error
3829 // (must process all streams).
3830 break;
3831 }
3832
3833 if (ret < 0 && ret != AVERROR(EAGAIN))
3834 {
3835 Logging::error(filename(), "Could not decode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
3836 return ret;
3837 }
3838
3839 lastret = ret;
3840
3841 pkt->data += decoded;
3842 pkt->size -= decoded;
3843 }
3844 while (pkt->size > 0 && (ret == 0 || ret == AVERROR(EAGAIN)));
3845
3846 ret = 0;
3847 }
3848#endif // USE_LIBDVD
3849 }
3850 else
3851 {
3852 // Simply copy packet without recoding
3853 pkt->stream_index = m_out.m_video.m_stream_idx;
3854
3855 // Rescale packet
3856 av_packet_rescale_ts(pkt, m_in.m_video.m_stream->time_base, m_out.m_video.m_stream->time_base);
3857
3858 // Make PTS/DTS if missing
3859 make_pts(pkt, &m_cur_video_ts);
3860
3861 pkt->pos = -1;
3862
3863 ret = store_packet(pkt, AVMEDIA_TYPE_VIDEO);
3864 }
3865 }
3866 else if (is_subtitle_stream(pkt->stream_index))
3867 {
3868 // Decode subtitle. No copy option available.
3869 int decoded = 0;
3870 ret = decode_subtitle(pkt, &decoded);
3871 }
3872 else
3873 {
3874 // Finally process album arts
3875 switch (m_in.m_format_ctx->streams[pkt->stream_index]->codecpar->codec_type)
3876 {
3877 case AVMEDIA_TYPE_VIDEO:
3878 {
3879 for (size_t n = 0; n < m_in.m_album_art.size() && n < m_out.m_album_art.size(); n++)
3880 {
3881 AVStream *input_stream = m_in.m_album_art.at(n).m_stream;
3882
3883 // AV_DISPOSITION_ATTACHED_PIC streams already processed in process_albumarts()
3884 if (pkt->stream_index == input_stream->index && !(input_stream->disposition & AV_DISPOSITION_ATTACHED_PIC))
3885 {
3886 AVStream *output_stream = m_out.m_album_art.at(n).m_stream;
3887
3888 ret = add_albumart_frame(output_stream, pkt);
3889 break;
3890 }
3891 }
3892 break;
3893 }
3894 default:
3895 {
3896 break;
3897 }
3898 }
3899 }
3900
3901 // If decoding errors should be ignored by command line, reset return code.
3902 // Exemptions that need to be passed on anyway:
3903 // * EAGAIN tells the caller to retry, this is not an error
3904 // * AVERROR_EXTERNAL is an unrecoverable error and should be handled
3905 if (!params.m_decoding_errors && ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EXTERNAL)
3906 {
3907 // Ignore error, go on with transcoding
3908 ret = 0;
3909 }
3910
3911 return ret;
3912}
3913
3914int FFmpeg_Transcoder::init_converted_samples(uint8_t ***converted_input_samples, int frame_size)
3915{
3916 int ret;
3917
3918 // Allocate as many pointers as there are audio channels.
3919 // Each pointer will later point to the audio samples of the corresponding
3920 // channels (although it may be nullptr for interleaved formats).
3921
3922 *converted_input_samples = static_cast<uint8_t **>(av_calloc(static_cast<size_t>(get_channels(m_out.m_audio.m_codec_ctx.get())), sizeof(**converted_input_samples)));
3923
3924 if (*converted_input_samples == nullptr)
3925 {
3926 Logging::error(virtname(), "Could not allocate converted input sample pointers.");
3927 return AVERROR(ENOMEM);
3928 }
3929
3930 // Allocate memory for the samples of all channels in one consecutive
3931 // block for convenience.
3932 ret = av_samples_alloc(*converted_input_samples, nullptr,
3934 frame_size,
3935 m_out.m_audio.m_codec_ctx->sample_fmt, 0);
3936 if (ret < 0)
3937 {
3938 Logging::error(virtname(), "Could not allocate converted input samples (error '%1').", ffmpeg_geterror(ret).c_str());
3939 av_freep(&(*converted_input_samples)[0]);
3940 av_free(*converted_input_samples);
3941 return ret;
3942 }
3943 return 0;
3944}
3945
3946int FFmpeg_Transcoder::convert_samples(uint8_t **input_data, int in_samples, uint8_t **converted_data, int *out_samples)
3947{
3948 if (m_audio_resample_ctx != nullptr)
3949 {
3950 int ret;
3951
3952 // Convert the samples using the resampler.
3953 ret = swr_convert(m_audio_resample_ctx, converted_data, *out_samples, const_cast<const uint8_t **>(input_data), in_samples);
3954 if (ret < 0)
3955 {
3956 Logging::error(virtname(), "Could not convert input samples (error '%1').", ffmpeg_geterror(ret).c_str());
3957 return ret;
3958 }
3959
3960 *out_samples = ret;
3961 }
3962 else
3963 {
3964 *out_samples = in_samples;
3965
3966 // No resampling, just copy samples
3967 if (!av_sample_fmt_is_planar(m_out.m_audio.m_codec_ctx->sample_fmt))
3968 {
3969 // Interleaved format
3970 int samples = in_samples * av_get_bytes_per_sample(m_out.m_audio.m_codec_ctx->sample_fmt) * get_channels(m_in.m_audio.m_codec_ctx.get());
3971 std::memcpy(converted_data[0], input_data[0], static_cast<size_t>(samples));
3972 }
3973 else
3974 {
3975 // Planar format
3976 int samples = in_samples * av_get_bytes_per_sample(m_out.m_audio.m_codec_ctx->sample_fmt);
3977 for (int n = 0; n < get_channels(m_out.m_audio.m_codec_ctx.get()); n++)
3978 {
3979 std::memcpy(converted_data[n], input_data[n], static_cast<size_t>(samples));
3980 }
3981 }
3982 }
3983 return 0;
3984}
3985
3986int FFmpeg_Transcoder::add_samples_to_fifo(uint8_t **converted_input_samples, int frame_size)
3987{
3988 int ret;
3989
3990 // Make the audio FIFO as large as it needs to be to hold both,
3991 // the old and the new samples.
3992
3993 ret = av_audio_fifo_realloc(m_audio_fifo, av_audio_fifo_size(m_audio_fifo) + frame_size);
3994 if (ret < 0)
3995 {
3996 Logging::error(virtname(), "Could not reallocate the audio FIFO.");
3997 return ret;
3998 }
3999
4000 // Store the new samples in the audio FIFO buffer.
4001 ret = av_audio_fifo_write(m_audio_fifo, reinterpret_cast<void **>(converted_input_samples), frame_size);
4002 if (ret < frame_size)
4003 {
4004 if (ret < 0)
4005 {
4006 Logging::error(virtname(), "Could not write data to audio FIFO (error '%1').", ffmpeg_geterror(ret).c_str());
4007 }
4008 else
4009 {
4010 Logging::error(virtname(), "Could not write data to audio FIFO.");
4011 }
4012 return AVERROR_EXIT;
4013 }
4014
4015 return 0;
4016}
4017
4018int FFmpeg_Transcoder::flush_frames_all(bool use_flush_packet)
4019{
4020 int ret = 0;
4021
4022 if (m_in.m_audio.m_codec_ctx != nullptr)
4023 {
4024 int ret2 = flush_frames_single(m_in.m_audio.m_stream_idx, use_flush_packet);
4025 if (ret2 < 0)
4026 {
4027 ret = ret2;
4028 }
4029 }
4030
4031 if (m_in.m_video.m_codec_ctx != nullptr)
4032 {
4033 int ret2 = flush_frames_single(m_in.m_video.m_stream_idx, use_flush_packet);
4034 if (ret2 < 0)
4035 {
4036 ret = ret2;
4037 }
4038 }
4039
4040 return ret;
4041}
4042
4043int FFmpeg_Transcoder::flush_frames_single(int stream_idx, bool use_flush_packet)
4044{
4045 int ret = 0;
4046
4047 if (stream_exists(stream_idx))
4048 {
4049 int (FFmpeg_Transcoder::*decode_frame_ptr)(AVPacket *pkt, int *decoded) = nullptr;
4050
4052 {
4053 decode_frame_ptr = &FFmpeg_Transcoder::decode_audio_frame;
4054 }
4056 {
4057 decode_frame_ptr = &FFmpeg_Transcoder::decode_video_frame;
4058 }
4059
4060 if (decode_frame_ptr != nullptr)
4061 {
4062#if !LAVC_DEP_AV_INIT_PACKET
4063 AVPacket pkt;
4064#endif // !LAVC_DEP_AV_INIT_PACKET
4065 AVPacket *flush_packet = nullptr;
4066
4067 if (use_flush_packet)
4068 {
4069#if LAVC_DEP_AV_INIT_PACKET
4070 flush_packet = av_packet_alloc();
4071#else // !LAVC_DEP_AV_INIT_PACKET
4072 flush_packet = &pkt;
4073
4074 init_packet(flush_packet);
4075#endif // !LAVC_DEP_AV_INIT_PACKET
4076
4077 flush_packet->data = nullptr;
4078 flush_packet->size = 0;
4079 flush_packet->stream_index = stream_idx;
4080 }
4081
4082 // cppcheck-suppress knownConditionTrueFalse
4083 for (int decoded = 1; decoded;)
4084 {
4085 ret = (this->*decode_frame_ptr)(flush_packet, &decoded);
4086 if (ret < 0 && ret != AVERROR(EAGAIN))
4087 {
4088 break;
4089 }
4090 }
4091
4092 av_packet_unref(flush_packet);
4093#if LAVC_DEP_AV_INIT_PACKET
4094 av_packet_free(&flush_packet);
4095#endif // LAVC_DEP_AV_INIT_PACKET
4096 }
4097 }
4098
4099 return ret;
4100}
4101
4103{
4104 // Packet used for temporary storage.
4105 AVPacket pkt;
4106 int ret = 0;
4107
4108 try
4109 {
4110 // Read one frame from the input file into a temporary packet.
4111 ret = av_read_frame(m_in.m_format_ctx, &pkt);
4112 if (ret < 0)
4113 {
4114 if (ret == AVERROR_EOF)
4115 {
4116 // If we are the the end of the file, flush the decoder below.
4117 *finished = 1;
4118 Logging::trace(virtname(), "Read input file to EOF.");
4119 }
4120 else
4121 {
4122 Logging::error(virtname(), "Could not read frame (error '%1').", ffmpeg_geterror(ret).c_str());
4123 throw ret;
4124 }
4125 }
4126
4128 {
4129 // Check for end of cue sheet track
4131 if (is_audio_stream(pkt.stream_index))
4132 {
4133 int64_t pkt_pts = ffmpeg_rescale_q(pkt.pts, m_in.m_audio.m_stream->time_base);
4135 {
4136 Logging::trace(virtname(), "Read to end of track.");
4137 *finished = 1;
4138 ret = AVERROR_EOF;
4139 }
4140 }
4141 }
4142
4143 if (!*finished)
4144 {
4145 // Decode one packet, at least with the old API (!LAV_NEW_PACKET_INTERFACE)
4146 // it seems a packet can contain more than one frame so loop around it
4147 // if necessary...
4148 ret = decode_frame(&pkt);
4149
4150 if (ret < 0 && ret != AVERROR(EAGAIN))
4151 {
4152 throw ret;
4153 }
4154 }
4155 else
4156 {
4157 // Flush cached frames, ignoring any errors
4158 flush_frames_all(true);
4159 }
4160
4161 ret = 0; // Errors will be reported by exception
4162 }
4163 catch (int _ret)
4164 {
4165 ret = _ret;
4166 }
4167
4168 av_packet_unref(&pkt);
4169
4170 return ret;
4171}
4172
4173int FFmpeg_Transcoder::init_audio_output_frame(AVFrame *frame, int frame_size) const
4174{
4175 int ret;
4176
4177 //
4178 // Set the frame's parameters, especially its size and format.
4179 // av_frame_get_buffer needs this to allocate memory for the
4180 // audio samples of the frame.
4181 // Default channel layouts based on the number of channels
4182 // are assumed for simplicity.
4183
4184 frame->nb_samples = frame_size;
4185#if LAVU_DEP_OLD_CHANNEL_LAYOUT
4186 ret = av_channel_layout_copy(&frame->ch_layout, &m_out.m_audio.m_codec_ctx->ch_layout);
4187 if (ret < 0)
4188 {
4189 Logging::error(virtname(), "Unable to copy channel layout (error '%1').", ffmpeg_geterror(ret).c_str());
4190 return ret;
4191 }
4192#else // !LAVU_DEP_OLD_CHANNEL_LAYOUT
4193 frame->channel_layout = m_out.m_audio.m_codec_ctx->channel_layout;
4194#endif // !LAVU_DEP_OLD_CHANNEL_LAYOUT
4195 frame->format = m_out.m_audio.m_codec_ctx->sample_fmt;
4196 frame->sample_rate = m_out.m_audio.m_codec_ctx->sample_rate;
4197
4198 // Allocate the samples of the created frame. This call will make
4199 // sure that the audio frame can hold as many samples as specified.
4200 // 29.05.2021: Let API decide about alignment. Should be properly set for the current CPU.
4201
4202 ret = av_frame_get_buffer(frame, 0);
4203 if (ret < 0)
4204 {
4205 Logging::error(virtname(), "Could allocate output frame samples (error '%1').", ffmpeg_geterror(ret).c_str());
4206 return ret;
4207 }
4208
4209 return 0;
4210}
4211
4213{
4214 if (pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE)
4215 {
4216 // Normally we have already added the PTS to the frame when it was created. Just in case
4217 // this failed, and there are no valid PTS/DTS values, we add it here.
4218 int64_t pkt_duration;
4219
4220 // Some encoders to not produce dts/pts.
4221 // So we make some up.
4222 if (pkt->duration)
4223 {
4224 pkt_duration = pkt->duration;
4225
4226#if !LAVC_DEP_TICKSPERFRAME
4227 // This has probably long since been fixed in FFmpeg, so we remove this completly
4228 // instead of replacing it with updated code.
4229 if (m_out.m_audio.m_codec_ctx->codec_id == AV_CODEC_ID_OPUS || m_current_format->filetype() == FILETYPE::TS || m_current_format->filetype() == FILETYPE::HLS)
4230 {
4237 if (pkt_duration > 0 && m_out.m_audio.m_stream->codecpar->sample_rate > 0)
4238 {
4239 pkt->duration = pkt_duration = static_cast<int>(av_rescale(pkt_duration, static_cast<int64_t>(m_out.m_audio.m_stream->time_base.den) * m_out.m_audio.m_codec_ctx->ticks_per_frame, m_out.m_audio.m_stream->codecpar->sample_rate * static_cast<int64_t>(m_out.m_audio.m_stream->time_base.num)));
4240 }
4241 }
4242#endif
4243 }
4244 else
4245 {
4246 pkt_duration = 1;
4247 }
4248
4249 pkt->dts = m_out.m_audio_pts - 1;
4250 pkt->pts = m_out.m_audio_pts;
4251
4252 m_out.m_audio_pts += pkt_duration;
4253 }
4254}
4255
4256int FFmpeg_Transcoder::encode_audio_frame(const AVFrame *frame, int *data_present)
4257{
4258 // Packet used for temporary storage.
4259#if !LAVC_DEP_AV_INIT_PACKET
4260 AVPacket tmp_pkt;
4261#endif // !LAVC_DEP_AV_INIT_PACKET
4262 AVPacket *pkt;
4263 int ret = 0;
4264
4265#if LAVC_DEP_AV_INIT_PACKET
4266 pkt = av_packet_alloc();
4267#else // !LAVC_DEP_AV_INIT_PACKET
4268 pkt = &tmp_pkt;
4269 init_packet(pkt);
4270#endif // !LAVC_DEP_AV_INIT_PACKET
4271
4272 try
4273 {
4274 // Encode the audio frame and store it in the temporary packet.
4275 // The output audio stream encoder is used to do this.
4276
4277 *data_present = 0;
4278
4279 // send the frame for encoding
4280 ret = avcodec_send_frame(m_out.m_audio.m_codec_ctx.get(), frame);
4281 if (ret < 0 && ret != AVERROR_EOF)
4282 {
4283 Logging::error(virtname(), "Could not encode audio frame (error %1').", ffmpeg_geterror(ret).c_str());
4284 throw ret;
4285 }
4286
4287 // read all the available output packets (in general there may be any number of them)
4288 while (ret >= 0)
4289 {
4290 *data_present = 0;
4291
4292 ret = avcodec_receive_packet(m_out.m_audio.m_codec_ctx.get(), pkt);
4293 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
4294 {
4295 throw ret;
4296 }
4297 else if (ret < 0)
4298 {
4299 Logging::error(virtname(), "Could not encode audio frame (error '%1').", ffmpeg_geterror(ret).c_str());
4300 throw ret;
4301 }
4302
4303 *data_present = 1;
4304
4305 // Write one audio frame from the temporary packet to the output buffer.
4306 {
4307 pkt->stream_index = m_out.m_audio.m_stream_idx;
4308
4309 produce_audio_dts(pkt);
4310
4311 ret = store_packet(pkt, AVMEDIA_TYPE_AUDIO);
4312 if (ret < 0)
4313 {
4314 throw ret;
4315 }
4316 }
4317 }
4318
4319 av_packet_unref(pkt);
4320 }
4321 catch (int _ret)
4322 {
4323 av_packet_unref(pkt);
4324 ret = _ret;
4325 }
4326
4327#if LAVC_DEP_AV_INIT_PACKET
4328 av_packet_free(&pkt);
4329#endif // LAVC_DEP_AV_INIT_PACKET
4330
4331 return ret;
4332}
4333
4334int FFmpeg_Transcoder::encode_image_frame(const AVFrame *frame, int *data_present)
4335{
4336 *data_present = 0;
4337
4338 if (frame == nullptr || m_skip_next_frame)
4339 {
4340 // This called internally to flush frames. We do not have a cache to flush, so simply ignore that.
4341 // After seek oprations we need to skip the first frame.
4342 m_skip_next_frame = false;
4343 return 0;
4344 }
4345
4346 if (m_current_format == nullptr)
4347 {
4348 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::encode_image_frame()! Missing format.");
4349 return AVERROR(EINVAL);
4350 }
4351
4352 if (m_buffer == nullptr)
4353 {
4354 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::encode_image_frame()! Cache not open.");
4355 return AVERROR(EINVAL);
4356 }
4357
4358#if !LAVC_DEP_AV_INIT_PACKET
4359 AVPacket tmp_pkt;
4360#endif // !LAVC_DEP_AV_INIT_PACKET
4361 AVPacket *pkt = nullptr;
4362 int ret = 0;
4363
4364 try
4365 {
4366 FFmpeg_Frame cloned_frame(frame); // Clone frame. Does not copy data but references it, only the properties are copied. Not a big memory impact.
4367
4368 ret = cloned_frame.res();
4369 if (ret < 0)
4370 {
4371 Logging::error(virtname(), "Could not encode image frame (error '%1').", ffmpeg_geterror(ret).c_str());
4372 throw ret;
4373 }
4374
4375#if LAVC_DEP_AV_INIT_PACKET
4376 pkt = av_packet_alloc();
4377#else // !LAVC_DEP_AV_INIT_PACKET
4378 pkt = &tmp_pkt;
4379 init_packet(pkt);
4380#endif // !LAVC_DEP_AV_INIT_PACKET
4381
4382 uint32_t frame_no = pts_to_frame(m_in.m_video.m_stream, frame->pts);
4383
4384 if (m_current_format->video_codec() == AV_CODEC_ID_MJPEG)
4385 {
4386 // The MJEPG codec requires monotonically growing PTS values so we fake some to avoid them going backwards after seeks
4387 cloned_frame->pts = frame_to_pts(m_in.m_video.m_stream, ++m_fake_frame_no);
4388 }
4389
4390 *data_present = 0;
4391
4392 // send the frame for encoding
4393 ret = avcodec_send_frame(m_out.m_video.m_codec_ctx.get(), cloned_frame);
4394 if (ret < 0 && ret != AVERROR_EOF)
4395 {
4396 Logging::error(virtname(), "Could not encode image frame (error '%1').", ffmpeg_geterror(ret).c_str());
4397 throw ret;
4398 }
4399
4400 // read all the available output packets (in general there may be any number of them
4401 while (ret >= 0)
4402 {
4403 *data_present = 0;
4404
4405 ret = avcodec_receive_packet(m_out.m_video.m_codec_ctx.get(), pkt);
4406 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
4407 {
4408 av_packet_unref(pkt);
4409 break;
4410 }
4411 else if (ret < 0)
4412 {
4413 Logging::error(virtname(), "Could not encode image frame (error '%1').", ffmpeg_geterror(ret).c_str());
4414 throw ret;
4415 }
4416
4417 *data_present = 1;
4418
4419 // Write one video frame from the temporary packet to the output buffer.
4420 {
4421 // Store current video PTS
4422 if (pkt->pts != AV_NOPTS_VALUE)
4423 {
4424 m_out.m_video_pts = pkt->pts;
4425 }
4426
4427 m_buffer->write_frame(pkt->data, static_cast<size_t>(pkt->size), frame_no);
4428
4429 if (m_last_seek_frame_no == frame_no) // Skip frames until seek pos
4430 {
4432 }
4433 }
4434
4435 av_packet_unref(pkt);
4436 }
4437 }
4438 catch (int _ret)
4439 {
4440 av_packet_unref(pkt);
4441 ret = _ret;
4442 }
4443
4444#if LAVC_DEP_AV_INIT_PACKET
4445 av_packet_free(&pkt);
4446#endif // LAVC_DEP_AV_INIT_PACKET
4447
4448 return ret;
4449}
4450
4451int FFmpeg_Transcoder::encode_video_frame(const AVFrame *frame, int *data_present)
4452{
4453 if (m_out.m_video.m_stream == nullptr)
4454 {
4455 return 0; // ignore, avoid crash
4456 }
4457
4458 // Packet used for temporary storage.
4459 if (frame != nullptr)
4460 {
4461#if LAVU_ADD_NEW_FRAME_FLAGS
4462 if (frame->flags & AV_FRAME_FLAG_INTERLACED)
4463 {
4464 if (m_out.m_video.m_codec_ctx->codec->id == AV_CODEC_ID_MJPEG)
4465 {
4466 m_out.m_video.m_stream->codecpar->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TT : AV_FIELD_BB;
4467 }
4468 else
4469 {
4470 m_out.m_video.m_stream->codecpar->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TB : AV_FIELD_BT;
4471 }
4472 }
4473#else // !LAVU_ADD_NEW_FRAME_FLAGS
4474 if (frame->interlaced_frame)
4475 {
4476 if (m_out.m_video.m_codec_ctx->codec->id == AV_CODEC_ID_MJPEG)
4477 {
4478 m_out.m_video.m_stream->codecpar->field_order = frame->top_field_first ? AV_FIELD_TT : AV_FIELD_BB;
4479 }
4480 else
4481 {
4482 m_out.m_video.m_stream->codecpar->field_order = frame->top_field_first ? AV_FIELD_TB : AV_FIELD_BT;
4483 }
4484 }
4485#endif // !LAVU_ADD_NEW_FRAME_FLAGS
4486 else
4487 {
4488 m_out.m_video.m_stream->codecpar->field_order = AV_FIELD_PROGRESSIVE;
4489 }
4490 }
4491#if !LAVC_DEP_AV_INIT_PACKET
4492 AVPacket tmp_pkt;
4493#endif // !LAVC_DEP_AV_INIT_PACKET
4494 FFmpeg_Frame *hw_frame = nullptr;
4495 AVPacket *pkt = nullptr;
4496 int ret = 0;
4497
4498 try
4499 {
4500 if (m_hwaccel_enable_enc_buffering && frame != nullptr)
4501 {
4502 hw_frame = new (std::nothrow) FFmpeg_Frame(m_out.m_video.m_stream_idx);
4503 if (hw_frame == nullptr)
4504 {
4505 ret = AVERROR(ENOMEM);
4506 Logging::error(virtname(), "Could not encode video frame at PTS=%1 (error %2').", ffmpeg_rescale_q(frame->pts, m_in.m_video.m_stream->time_base), ffmpeg_geterror(ret).c_str());
4507 throw ret;
4508 }
4509
4510 ret = hw_frame->res();
4511 if (ret < 0)
4512 {
4513 Logging::error(virtname(), "Could not encode video frame at PTS=%1 (error %2').", ffmpeg_rescale_q(frame->pts, m_in.m_video.m_stream->time_base), ffmpeg_geterror(ret).c_str());
4514 throw ret;
4515 }
4516
4517 // If encoding is done in hardware, the resulting frame data needs to be copied to hardware
4518 ret = hwframe_copy_to_hw(m_out.m_video.m_codec_ctx.get(), hw_frame, frame);
4519 if (ret < 0)
4520 {
4521 throw ret;
4522 }
4523 frame = *hw_frame; // Copy, not clone!
4524 }
4525
4526#if LAVC_DEP_AV_INIT_PACKET
4527 pkt = av_packet_alloc();
4528#else // !LAVC_DEP_AV_INIT_PACKET
4529 pkt = &tmp_pkt;
4530 init_packet(pkt);
4531#endif // !LAVC_DEP_AV_INIT_PACKET
4532
4533 // Encode the video frame and store it in the temporary packet.
4534 // The output video stream encoder is used to do this.
4535
4536 *data_present = 0;
4537
4538 // send the frame for encoding
4539 ret = avcodec_send_frame(m_out.m_video.m_codec_ctx.get(), frame);
4540 if (ret < 0 && ret != AVERROR_EOF)
4541 {
4542 Logging::error(virtname(), "Could not encode video frame (error %1').", ffmpeg_geterror(ret).c_str());
4543 throw ret;
4544 }
4545
4546 // read all the available output packets (in general there may be any number of them
4547 while (ret >= 0)
4548 {
4549 *data_present = 0;
4550
4551 ret = avcodec_receive_packet(m_out.m_video.m_codec_ctx.get(), pkt);
4552 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
4553 {
4554 av_packet_unref(pkt);
4555 break;
4556 }
4557 else if (ret < 0)
4558 {
4559 Logging::error(virtname(), "Could not encode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
4560 throw ret;
4561 }
4562
4563 *data_present = 1;
4564
4565 // Write one video frame from the temporary packet to the output buffer.
4566 {
4567 // Fix for issue #46: bitrate too high.
4568 av_packet_rescale_ts(pkt, m_out.m_video.m_codec_ctx->time_base, m_out.m_video.m_stream->time_base);
4569
4570 if (!(m_out.m_format_ctx->oformat->flags & AVFMT_NOTIMESTAMPS))
4571 {
4572 if (pkt->dts != AV_NOPTS_VALUE &&
4573 pkt->pts != AV_NOPTS_VALUE &&
4574 pkt->dts > pkt->pts &&
4575 m_out.m_last_mux_dts != AV_NOPTS_VALUE)
4576 {
4577
4578 Logging::warning(virtname(), "Invalid DTS=%1 PTS=%2 in video output, replacing by guess.", pkt->dts, pkt->pts);
4579
4580 pkt->pts =
4581 pkt->dts = pkt->pts + pkt->dts + m_out.m_last_mux_dts + 1
4582 - FFMIN3(pkt->pts, pkt->dts, m_out.m_last_mux_dts + 1)
4583 - FFMAX3(pkt->pts, pkt->dts, m_out.m_last_mux_dts + 1);
4584 }
4585
4586 if (pkt->dts != AV_NOPTS_VALUE && m_out.m_last_mux_dts != AV_NOPTS_VALUE)
4587 {
4588 int64_t max = m_out.m_last_mux_dts + !(m_out.m_format_ctx->oformat->flags & AVFMT_TS_NONSTRICT);
4589 // AVRational avg_frame_rate = { m_out.m_video.m_stream->avg_frame_rate.den, m_out.m_video.m_stream->avg_frame_rate.num };
4590 // int64_t max = m_out.m_last_mux_dts + ffmpeg_rescale_q(1, avg_frame_rate, m_out.m_video.m_stream->time_base);
4591
4592 if (pkt->dts < max)
4593 {
4594 Logging::trace(virtname(), "Non-monotonous DTS in video output stream; previous: %1, current: %2; changing to %3. This may result in incorrect timestamps in the output.", m_out.m_last_mux_dts, pkt->dts, max);
4595
4596 if (pkt->pts >= pkt->dts)
4597 {
4598 pkt->pts = FFMAX(pkt->pts, max);
4599 }
4600 pkt->dts = max;
4601 }
4602 }
4603 }
4604
4605 if (frame != nullptr && !pkt->duration)
4606 {
4607#if !LAVU_DEP_PKT_DURATION
4608 pkt->duration = frame->pkt_duration;
4609#else
4610 pkt->duration = frame->duration;
4611#endif
4612 }
4613
4614 if (pkt->pts != AV_NOPTS_VALUE)
4615 {
4616 m_out.m_video_pts = pkt->pts;
4617 m_out.m_last_mux_dts = (pkt->dts != AV_NOPTS_VALUE) ? pkt->dts : (pkt->pts - pkt->duration);
4618 }
4619
4620 // Write packet to buffer
4621 ret = store_packet(pkt, AVMEDIA_TYPE_VIDEO);
4622 if (ret < 0)
4623 {
4624 throw ret;
4625 }
4626 }
4627
4628 av_packet_unref(pkt);
4629 }
4630 }
4631 catch (int _ret)
4632 {
4633 if (pkt != nullptr)
4634 {
4635 av_packet_unref(pkt);
4636 }
4637 ret = _ret;
4638 }
4639
4640 delete hw_frame;
4641
4642#if LAVC_DEP_AV_INIT_PACKET
4643 av_packet_free(&pkt);
4644#endif // LAVC_DEP_AV_INIT_PACKET
4645
4646 return ret;
4647}
4648
4649int FFmpeg_Transcoder::encode_subtitle(const AVSubtitle *sub, int out_stream_idx, int *data_present)
4650{
4651 StreamRef * out_streamref = get_out_subtitle_stream(out_stream_idx);
4652
4653 *data_present = 0;
4654
4655 if (out_streamref == nullptr)
4656 {
4657 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::encode_subtitle()! Invalid stream index #%1.", out_stream_idx);
4658 return AVERROR(EINVAL);
4659 }
4660
4661 // Packet used for temporary storage.
4662#if !LAVC_DEP_AV_INIT_PACKET
4663 AVPacket tmp_pkt;
4664#endif // !LAVC_DEP_AV_INIT_PACKET
4665 AVPacket *pkt;
4666 int ret = 0;
4667
4668#if LAVC_DEP_AV_INIT_PACKET
4669 pkt = av_packet_alloc();
4670#else // !LAVC_DEP_AV_INIT_PACKET
4671 pkt = &tmp_pkt;
4672 init_packet(pkt);
4673#endif // !LAVC_DEP_AV_INIT_PACKET
4674
4675 AVSubtitle subtmp;
4676
4677 // Make a local copy, we have to modify it
4678 std::memcpy(&subtmp, sub, sizeof(AVSubtitle));
4679
4680 try
4681 {
4682 int nb;
4683 int64_t sub_pts;
4684
4685 if (subtmp.pts == AV_NOPTS_VALUE)
4686 {
4687 Logging::error(virtname(), "Subtitle packets must have a PTS (stream index #%1).", out_streamref->m_stream_idx);
4688 throw AVERROR(EINVAL);
4689 }
4690
4691 // Allocate a packet with 1KB buffer, hope that's sufficient
4692 ret = av_new_packet(pkt, 1024 * 1024);
4693 if (ret < 0)
4694 {
4695 Logging::error(virtname(), "Failed to allocate new packet (error '%1').", ffmpeg_geterror(ret).c_str());
4696 throw ret;
4697 }
4698
4699 // Note: DVB subtitles need one packet to draw them and one other packet to clear them
4700 if (out_streamref->m_codec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
4701 {
4702 nb = 2;
4703 }
4704 else
4705 {
4706 nb = 1;
4707 }
4708
4709 // shift timestamp
4710 sub_pts = subtmp.pts;
4711
4712 //if (out_streamref->m_stream->start_time != AV_NOPTS_VALUE)
4713 //{
4714 // pts -= ffmpeg_rescale_q(out_streamref->m_stream->start_time, out_streamref->m_stream->time_base);
4715 //}
4716
4717 for (int i = 0; i < nb; i++)
4718 {
4719 unsigned save_num_rects = subtmp.num_rects;
4720 subtmp.pts = sub_pts;
4721 // Some decoders may return end_display_time as UINT32_MAX, this causes strange results.
4722 if (subtmp.end_display_time == UINT32_MAX)
4723 {
4724 subtmp.end_display_time = 0;
4725 }
4726
4727 // start_display_time is required to be 0
4728 subtmp.pts += ffmpeg_rescale_q(subtmp.start_display_time, AVRational({ 1, 1000 }));
4729 subtmp.end_display_time -= subtmp.start_display_time;
4730 subtmp.start_display_time = 0;
4731 if (i == 1)
4732 {
4733 subtmp.num_rects = 0;
4734 }
4735
4736 // The avcodec_encode_subtitle seems to be not completely ready
4737 ret = avcodec_encode_subtitle(out_streamref->m_codec_ctx.get(), pkt->data, pkt->size, &subtmp);
4738 if (i == 1)
4739 {
4740 subtmp.num_rects = save_num_rects;
4741 }
4742
4743 if (ret < 0)
4744 {
4745 Logging::error(virtname(), "Could not encode subtitle frame (error '%1').", ffmpeg_geterror(ret).c_str());
4746 throw ret;
4747 }
4748
4749 pkt->size = ret;
4750 pkt->pts = ffmpeg_rescale_q(subtmp.pts, av_get_time_base_q(), out_streamref->m_stream->time_base);
4751 pkt->duration = ffmpeg_rescale_q(subtmp.end_display_time, AVRational({ 1, 1000 }), out_streamref->m_stream->time_base);
4752 pkt->stream_index = out_streamref->m_stream_idx;
4753
4754 if (out_streamref->m_codec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
4755 {
4756 // the pts correction is handled here. Maybe handling it in the codec would be better
4757 if (i)
4758 {
4759 pkt->pts += ffmpeg_rescale_q(subtmp.end_display_time, AVRational({ 1, 1000 }), out_streamref->m_stream->time_base);
4760 }
4761 }
4762 pkt->dts = pkt->pts;
4763
4764 ret = store_packet(pkt, AVMEDIA_TYPE_SUBTITLE);
4765 if (ret < 0)
4766 {
4767 throw ret;
4768 }
4769
4770 *data_present = 1;
4771 }
4772 av_packet_unref(pkt);
4773 }
4774 catch (int _ret)
4775 {
4776 av_packet_unref(pkt);
4777 ret = _ret;
4778 }
4779
4780#if LAVC_DEP_AV_INIT_PACKET
4781 av_packet_free(&pkt);
4782#endif // LAVC_DEP_AV_INIT_PACKET
4783
4784 return ret;
4785}
4786
4788{
4789 // Temporary storage of the output samples of the frame written to the file.
4790 FFmpeg_Frame output_frame(m_out.m_audio.m_stream_idx);
4791 int ret = 0;
4792
4793 ret = output_frame.res();
4794 if (ret < 0)
4795 {
4796 Logging::error(virtname(), "Could not read data from the audio FIFO (error '%1').", ffmpeg_geterror(ret).c_str());
4797 return ret;
4798 }
4799
4800 // Use the maximum number of possible samples per frame.
4801 // If there is less than the maximum possible frame size in the audio FIFO
4802 // buffer use this number. Otherwise, use the maximum possible frame size
4803
4804 frame_size = FFMIN(av_audio_fifo_size(m_audio_fifo), frame_size);
4805
4806 // Initialise temporary storage for one output frame.
4807 ret = init_audio_output_frame(output_frame, frame_size);
4808 if (ret < 0)
4809 {
4810 return ret;
4811 }
4812
4813 // Read as many samples from the FIFO buffer as required to fill the frame.
4814 // The samples are stored in the frame temporarily.
4815
4816 ret = av_audio_fifo_read(m_audio_fifo, reinterpret_cast<void **>(output_frame->data), frame_size);
4817 if (ret < frame_size)
4818 {
4819 if (ret < 0)
4820 {
4821 Logging::error(virtname(), "Could not read data from the audio FIFO (error '%1').", ffmpeg_geterror(ret).c_str());
4822 }
4823 else
4824 {
4825 Logging::error(virtname(), "Could not read data from the audio FIFO.");
4826 ret = AVERROR_EXIT;
4827 }
4828 return ret;
4829 }
4830
4831 // Build correct PTS
4832 if (output_frame->sample_rate)
4833 {
4834 /*
4835 * FFmpeg API docs say:
4836 *
4837 * best_effort_timestamp: frame timestamp estimated using various heuristics, in stream time base.
4838 * Unused for encoding, but we set it anyways.
4839 *
4840 * pts: Presentation timestamp, they say in ffmpeg time_base units, but nevertheless it seems to be
4841 * in stream time base. When not converted the audio comes out wobbly.
4842 */
4843
4844 // Not sure if this is use anywhere, but let's set it anyway.
4845 output_frame->best_effort_timestamp = ffmpeg_rescale_q(m_out.m_audio_pts, m_out.m_audio.m_stream->time_base, m_in.m_audio.m_stream->time_base);
4846 output_frame->pts = m_out.m_audio_pts;
4847
4848 // duration = `a * b / c` = AV_TIME_BASE * output_frame->nb_samples / output_frame->sample_rate;
4849 int64_t sample_duration = av_rescale(AV_TIME_BASE, output_frame->nb_samples, output_frame->sample_rate);
4850
4851 sample_duration = ffmpeg_rescale_q(sample_duration, av_get_time_base_q(), m_out.m_audio.m_stream->time_base);
4852
4853 m_out.m_audio_pts += sample_duration;
4854 }
4855
4856 int64_t pos = ffmpeg_rescale_q_rnd(output_frame->pts - m_out.m_audio.m_start_time, m_out.m_audio.m_stream->time_base);
4857
4858 m_frame_map.insert(std::make_pair(pos, output_frame));
4859
4860 return ret;
4861}
4862
4864{
4865 int ret;
4866
4867 ret = av_write_trailer(m_out.m_format_ctx);
4868 if (ret < 0)
4869 {
4870 Logging::error(virtname(), "Could not write output file trailer (error '%1').", ffmpeg_geterror(ret).c_str());
4871 return ret;
4872 }
4873
4874 return 0;
4875}
4876
4878{
4879 return m_mtime;
4880}
4881
4882template <size_t size>
4883const char * FFmpeg_Transcoder::tagcpy(char (&out) [ size ], const std::string & in) const // NOLINT(modernize-avoid-c-arrays)
4884{
4885 std::memset(out, ' ', size);
4886 std::memcpy(out, in.c_str(), std::min(size, in.size()));
4887 return out;
4888}
4889
4890template <class T>
4891const T & FFmpeg_Transcoder::tagcpy(T & out, const std::string & in) const
4892{
4893 out.fill(' ');
4894 std::memcpy(out.data(), in.c_str(), std::min(out.size(), in.size()));
4895// std::memset(out, ' ', size);
4896// std::memcpy(out, in.c_str(), std::min(size, in.size()));
4897 return out;
4898}
4899
4900
4901void FFmpeg_Transcoder::copy_metadata(AVDictionary **metadata_out, const AVDictionary *metadata_in, bool contentstream)
4902{
4903 AVDictionaryEntry *tag = nullptr;
4904
4905 while ((tag = av_dict_get(metadata_in, "", tag, AV_DICT_IGNORE_SUFFIX)) != nullptr)
4906 {
4907 std::string value(tag->value);
4908
4909 if (contentstream && m_virtualfile != nullptr && m_virtualfile->m_flags & VIRTUALFLAG_CUESHEET)
4910 {
4911 // Replace tags with cue sheet values
4912 if (!strcasecmp(tag->key, "ARTIST"))
4913 {
4915 }
4916 else if (!strcasecmp(tag->key, "TITLE"))
4917 {
4919 }
4920 else if (!strcasecmp(tag->key, "TRACK"))
4921 {
4923 }
4924 }
4925
4926 dict_set_with_check(metadata_out, tag->key, value.c_str(), 0, virtname());
4927
4928 if (contentstream && m_out.m_filetype == FILETYPE::MP3)
4929 {
4930 // For MP3 fill in ID3v1 structure
4931 if (!strcasecmp(tag->key, "ARTIST"))
4932 {
4933 tagcpy(m_out.m_id3v1.m_artist, value);
4934 }
4935 else if (!strcasecmp(tag->key, "TITLE"))
4936 {
4937 tagcpy(m_out.m_id3v1.m_title, value);
4938 }
4939 else if (!strcasecmp(tag->key, "ALBUM"))
4940 {
4941 tagcpy(m_out.m_id3v1.m_album, value);
4942 }
4943 else if (!strcasecmp(tag->key, "COMMENT"))
4944 {
4945 tagcpy(m_out.m_id3v1.m_comment, value);
4946 }
4947 else if (!strcasecmp(tag->key, "YEAR") || !strcasecmp(tag->key, "DATE"))
4948 {
4949 tagcpy(m_out.m_id3v1.m_year, value);
4950 }
4951 else if (!strcasecmp(tag->key, "TRACK"))
4952 {
4953 m_out.m_id3v1.m_title_no = static_cast<char>(std::stoi(value));
4954 }
4955 }
4956 }
4957}
4958
4960{
4961 Logging::trace(virtname(), "Processing metadata.");
4962
4963 if (m_in.m_audio.m_stream != nullptr && m_in.m_audio.m_stream->codecpar->codec_id == AV_CODEC_ID_VORBIS)
4964 {
4965 // For some formats (namely ogg) FFmpeg returns the tags, odd enough, with streams...
4966 copy_metadata(&m_out.m_format_ctx->metadata, m_in.m_audio.m_stream->metadata);
4967 }
4968
4969 copy_metadata(&m_out.m_format_ctx->metadata, m_in.m_format_ctx->metadata);
4970
4971 if (m_out.m_audio.m_stream != nullptr && m_in.m_audio.m_stream != nullptr)
4972 {
4973 // Copy audio stream meta data
4974 copy_metadata(&m_out.m_audio.m_stream->metadata, m_in.m_audio.m_stream->metadata);
4975 }
4976
4977 if (m_out.m_video.m_stream != nullptr && m_in.m_video.m_stream != nullptr)
4978 {
4979 // Copy video stream meta data
4980 copy_metadata(&m_out.m_video.m_stream->metadata, m_in.m_video.m_stream->metadata);
4981 }
4982
4983 // Also copy album art meta tags
4984 for (size_t n = 0; n < m_in.m_album_art.size() && n < m_out.m_album_art.size(); n++)
4985 {
4986 AVStream *input_stream = m_in.m_album_art.at(n).m_stream;
4987 AVStream *output_stream = m_out.m_album_art.at(n).m_stream;
4988
4989 copy_metadata(&output_stream->metadata, input_stream->metadata, is_audio_stream(input_stream->index) || is_video_stream(input_stream->index));
4990 }
4991
4993 {
4996 dict_set_with_check(&m_out.m_format_ctx->metadata, "ARTIST", m_virtualfile->m_cuesheet_track.m_artist.c_str(), 0, virtname(), true);
4997 if (av_dict_get(m_out.m_format_ctx->metadata, "ALBUM_ARTIST", nullptr, 0) == nullptr)
4998 {
4999 // Issue #78: duplicate ARTIST tag to ALBUM_ARTIST, if target is empty.
5000 dict_set_with_check(&m_out.m_format_ctx->metadata, "ALBUM_ARTIST", m_virtualfile->m_cuesheet_track.m_artist.c_str(), 0, virtname(), true);
5001 }
5002 dict_set_with_check(&m_out.m_format_ctx->metadata, "TITLE", m_virtualfile->m_cuesheet_track.m_title.c_str(), 0, virtname(), true);
5003 dict_set_with_check(&m_out.m_format_ctx->metadata, "ALBUM", m_virtualfile->m_cuesheet_track.m_album.c_str(), 0, virtname(), true);
5004 dict_set_with_check(&m_out.m_format_ctx->metadata, "GENRE", m_virtualfile->m_cuesheet_track.m_genre.c_str(), 0, virtname(), true);
5005 dict_set_with_check(&m_out.m_format_ctx->metadata, "DATE", m_virtualfile->m_cuesheet_track.m_date.c_str(), 0, virtname(), true);
5006 }
5007
5008 return 0;
5009}
5010
5012{
5013 int ret = 0;
5014
5015 for (size_t n = 0; n < m_in.m_album_art.size() && n < m_out.m_album_art.size(); n++)
5016 {
5017 AVStream *input_stream = m_in.m_album_art.at(n).m_stream;
5018
5019 if (input_stream->disposition & AV_DISPOSITION_ATTACHED_PIC)
5020 {
5021 AVStream *output_stream = m_out.m_album_art.at(n).m_stream;
5022
5023 ret = add_albumart_frame(output_stream, &input_stream->attached_pic);
5024 if (ret < 0)
5025 {
5026 break;
5027 }
5028 }
5029 }
5030
5031 return ret;
5032}
5033
5035{
5036 if (m_in.m_audio.m_codec_ctx != nullptr)
5037 {
5038 avcodec_flush_buffers(m_in.m_audio.m_codec_ctx.get());
5039 }
5040 if (m_in.m_video.m_codec_ctx != nullptr)
5041 {
5042 avcodec_flush_buffers(m_in.m_video.m_codec_ctx.get());
5043 }
5044}
5045
5047{
5048 m_have_seeked = true; // Note that we have seeked, thus skipped frames. We need to start transcoding over to fill any gaps.
5049
5050 //m_skip_next_frame = true; /**< @todo Take deinterlace into account. If deinterlace is on the frame number is decreased by one. */
5051
5053 {
5054 --frame_no;
5055 }
5056
5057 int64_t vstream_pts = frame_to_pts(m_in.m_video.m_stream, frame_no);
5058
5059 if (m_in.m_video.m_stream->start_time != AV_NOPTS_VALUE)
5060 {
5061 vstream_pts += m_in.m_video.m_stream->start_time;
5062 }
5063
5064 return av_seek_frame(m_in.m_format_ctx, m_in.m_video.m_stream_idx, vstream_pts, AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME);
5065}
5066
5067int FFmpeg_Transcoder::skip_decoded_frames(uint32_t frame_no, bool forced_seek)
5068{
5069 int ret = 0;
5070 uint32_t next_frame_no = frame_no;
5071
5072 // Seek next undecoded frame
5073 for (; m_buffer->have_frame(next_frame_no); next_frame_no++)
5074 {
5075 std::this_thread::yield();
5076 }
5077
5078 if (next_frame_no > m_virtualfile->m_video_frame_count)
5079 {
5080 // Reached end of file
5081 // Set PTS to end of file
5083 if (m_in.m_video.m_stream->start_time != AV_NOPTS_VALUE)
5084 {
5085 m_out.m_video_pts += m_in.m_video.m_stream->start_time;
5086 }
5087 // Seek to end of file to force AVERROR_EOF from next av_read_frame() call. Ignore errrors.
5088 av_seek_frame(m_in.m_format_ctx, m_in.m_video.m_stream_idx, m_out.m_video_pts, AVSEEK_FLAG_ANY);
5089 return 0;
5090 }
5091
5092 uint32_t last_frame_no = pts_to_frame(m_in.m_video.m_stream, m_out.m_video_pts);
5093
5094 // Ignore seek if target is within the next FRAME_SEEK_THRESHOLD frames
5095 if (next_frame_no >= last_frame_no /*+ 1*/ && next_frame_no <= last_frame_no + FRAME_SEEK_THRESHOLD)
5096 {
5097 return 0;
5098 }
5099
5100 if (forced_seek || (frame_no != next_frame_no && next_frame_no > 1))
5101 {
5102 // If frame changed, skip to it
5103 ret = do_seek_frame(next_frame_no);
5104
5105 if (ret < 0)
5106 {
5107 Logging::error(virtname(), "Could not encode audio frame: Seek to frame #%1 failed (error '%2').", next_frame_no, ffmpeg_geterror(ret).c_str());
5108 }
5109 }
5110
5111 return ret;
5112}
5113
5115{
5116 int ret = 0;
5117
5118 if (m_out.m_audio.m_codec_ctx != nullptr)
5119 {
5120 // Flush the encoder as it may have delayed frames.
5121 int data_written = 0;
5122 do
5123 {
5124 ret = encode_audio_frame(nullptr, &data_written);
5125
5126 if (ret == AVERROR_EOF)
5127 {
5128 // Not an error
5129 break;
5130 }
5131
5132 if (ret < 0 && ret != AVERROR(EAGAIN))
5133 {
5134 Logging::error(virtname(), "Could not encode audio frame (error '%1').", ffmpeg_geterror(ret).c_str());
5135 break;
5136 }
5137 }
5138 while (data_written);
5139 }
5140
5141 return ret;
5142}
5143
5145{
5146 int ret = 0;
5147
5148 if (m_out.m_video.m_codec_ctx != nullptr)
5149 {
5150 // Flush the encoder as it may have delayed frames.
5151 int data_written = 0;
5152 do
5153 {
5154 if (!is_frameset())
5155 {
5156 // Encode regular frame
5157 ret = encode_video_frame(nullptr, &data_written);
5158 }
5159 else
5160 {
5161 // Encode seperate image frame
5162 ret = encode_image_frame(nullptr, &data_written);
5163 }
5164
5165 if (ret == AVERROR_EOF)
5166 {
5167 // Not an error
5168 break;
5169 }
5170 if (ret < 0 && ret != AVERROR(EAGAIN))
5171 {
5172 Logging::error(virtname(), "Could not encode video frame (error '%1').", ffmpeg_geterror(ret).c_str());
5173 break;
5174 }
5175 }
5176 while (data_written);
5177 }
5178
5179 return ret;
5180}
5181
5183{
5184 return 0;
5185}
5186
5188{
5189 int output_frame_size;
5190
5191 if (m_out.m_audio.m_codec_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
5192 {
5193 // Encode supports variable frame size, use an arbitrary value
5194 output_frame_size = 10000;
5195 }
5196 else
5197 {
5198 // Use the encoder's desired frame size for processing.
5199 output_frame_size = m_out.m_audio.m_codec_ctx->frame_size;
5200 }
5201
5202 // Make sure that there is one frame worth of samples in the audio FIFO
5203 // buffer so that the encoder can do its work.
5204 // Since the decoder's and the encoder's frame size may differ, we
5205 // need to FIFO buffer to store as many frames worth of input samples
5206 // that they make up at least one frame worth of output samples.
5207
5208 while (av_audio_fifo_size(m_audio_fifo) < output_frame_size)
5209 {
5210 int ret = 0;
5211
5212 // Decode one frame worth of audio samples, convert it to the
5213 // output sample format and put it into the audio FIFO buffer.
5214
5215 ret = read_decode_convert_and_store(finished);
5216 if (ret < 0)
5217 {
5218 return ret;
5219 }
5220
5221 // If we are at the end of the input file, we continue
5222 // encoding the remaining audio samples to the output file.
5223
5224 if (*finished)
5225 {
5226 break;
5227 }
5228 }
5229
5230 // If we have enough samples for the encoder, we encode them.
5231 // At the end of the file, we pass the remaining samples to
5232 // the encoder.
5233
5234 while (av_audio_fifo_size(m_audio_fifo) >= output_frame_size || (*finished && av_audio_fifo_size(m_audio_fifo) > 0))
5235 {
5236 int ret = 0;
5237
5238 // Take one frame worth of audio samples from the audio FIFO buffer,
5239 // create a frame and store in audio frame buffer.
5240
5241 ret = create_audio_frame(output_frame_size);
5242 if (ret < 0)
5243 {
5244 return ret;
5245 }
5246 }
5247
5248 return 0;
5249}
5250
5252{
5253 int finished = 0;
5254
5256
5257 try
5258 {
5259 if (m_in.m_video.m_stream != nullptr && is_frameset())
5260 {
5261 int ret = 0;
5262
5263 // Direct access handling for frame sets: seek to frame if requested.
5264 ret = seek_frame();
5265 if (ret == AVERROR_EOF)
5266 {
5267 *status = DECODER_STATUS::DEC_EOF; // Report EOF, but return no error
5268 throw 0;
5269 }
5270
5271 if (ret < 0)
5272 {
5273 throw ret;
5274 }
5275 }
5276
5278 {
5279 int ret = 0;
5280
5281 // Copy audio FIFO into frame buffer
5282 ret = copy_audio_to_frame_buffer(&finished);
5283 if (ret < 0)
5284 {
5285 throw ret;
5286 }
5287 }
5288 else
5289 {
5290 int ret = 0;
5291
5292 // If we have no audio stream, we'll only get video data
5293 // or we simply copy audio and/or video frames into the packet queue
5294 ret = read_decode_convert_and_store(&finished);
5295 if (ret < 0)
5296 {
5297 throw ret;
5298 }
5299
5300 if (finished)
5301 {
5302 *status = DECODER_STATUS::DEC_EOF; // Report EOF
5303 }
5304 }
5305
5306 do
5307 {
5308 if (!is_frameset())
5309 {
5310 int64_t delay;
5311
5312 // The following values are arbitrarily chosen and seem to work.
5313 if (is_hls())
5314 {
5315 delay = params.m_segment_duration * 75 / 100; // 75% of the segment duration
5316 }
5317 else
5318 {
5319 delay = 6 * AV_TIME_BASE; // 6 seconds
5320 }
5321
5322 if (!finished && (!m_frame_map.empty() && m_frame_map.cbegin()->first + delay > m_frame_map.crbegin()->first))
5323 {
5324 return 0;
5325 }
5326
5327 while (!m_frame_map.empty())
5328 {
5329 // Take first entry in map
5330 MULTIFRAME_MAP::const_iterator it = m_frame_map.cbegin();
5331
5332 if (is_hls())
5333 {
5334 uint32_t next_segment = get_next_segment(it->first);
5335
5336 if (goto_next_segment(next_segment))
5337 {
5338 // Reached next segment, end current now, and force new.
5340 break;
5341 }
5342 }
5343
5344 // Get multiframe from map
5345 MULTIFRAME multiframe = it->second;
5346
5347 // Drop key from map, we've got a clone in multiframe now.
5348 m_frame_map.erase(it);
5349
5350 if (std::holds_alternative<FFmpeg_Frame>(multiframe))
5351 {
5352 // Object is an audio/video frame
5353 const FFmpeg_Frame & frame = std::get<FFmpeg_Frame>(multiframe);
5354
5355 int stream_idx = frame.m_stream_idx;
5356
5357 if (!stream_exists(stream_idx))
5358 {
5359 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::process_single_fr()! Invalid stream index in audio/video buffer skipped.");
5360 continue;
5361 }
5362
5363 if (stream_idx == m_out.m_audio.m_stream_idx)
5364 {
5365 // Encode audio
5366 int ret = 0;
5367 int data_written;
5368
5369 // Encode one frame worth of audio samples.
5370 ret = encode_audio_frame(frame, &data_written);
5371
5372 if (ret < 0 && ret != AVERROR(EAGAIN))
5373 {
5374 throw ret;
5375 }
5376 }
5377 else if (stream_idx == m_out.m_video.m_stream_idx)
5378 {
5379 // Encode video
5380 int ret = 0;
5381 int data_written = 0;
5382 ret = encode_video_frame(frame, &data_written);
5383
5384 if (ret < 0 && ret != AVERROR(EAGAIN))
5385 {
5386 throw ret;
5387 }
5388 }
5389 }
5390 else if (std::holds_alternative<FFmpeg_Subtitle>(multiframe))
5391 {
5392 // Object is a subtitle
5393 const FFmpeg_Subtitle & subtitle = std::get<FFmpeg_Subtitle>(multiframe);
5394
5395 int stream_idx = subtitle.m_stream_idx;
5396
5397 if (!stream_exists(stream_idx))
5398 {
5399 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::process_single_fr()! Invalid stream index in subtitle buffer skipped.");
5400 continue;
5401 }
5402
5403 // Encode subtitles
5404
5405 int ret = 0;
5406 int data_written = 0;
5407
5408 ret = encode_subtitle(subtitle, stream_idx, &data_written);
5409
5410 if (ret < 0 && ret != AVERROR(EAGAIN))
5411 {
5412 throw ret;
5413 }
5414 }
5415 }
5416 }
5417 else
5418 {
5419 // Frame sets: no audio, no subtitles, no output stream (index)
5420 while (!m_frame_map.empty())
5421 {
5422 // Although I abhore "auto", it seems that nodes are declared slightly different throughout
5423 // several std::map implementations. To avoid #ifdef orgies, I resign: Using "auto" here
5424 // is much more coherent.
5425 auto nh = m_frame_map.extract(m_frame_map.cbegin());
5426 const MULTIFRAME & multiframe = nh.mapped();
5427 int ret = 0;
5428 int data_written = 0;
5429
5430 // Encode video
5431 ret = encode_image_frame(std::get<FFmpeg_Frame>(multiframe), &data_written);
5432
5433 if (ret < 0 && ret != AVERROR(EAGAIN))
5434 {
5435 throw ret;
5436 }
5437 }
5438 }
5439
5441 {
5442 // Start new HLS segment
5443 int ret = 0;
5444
5445 ret = start_new_segment();
5446 if (ret < 0)
5447 {
5448 throw ret;
5449 }
5450 }
5451 } while (finished && !m_frame_map.empty()); // Ensure we've processed all frames in our buffer
5452
5453 // If we are at the end of the input file and have encoded
5454 // all remaining samples, we can exit this loop and finish.
5455
5456 if (finished && m_frame_map.empty())
5457 {
5461
5462 *status = DECODER_STATUS::DEC_EOF; // Report EOF
5463 }
5464 }
5465 catch (int _ret)
5466 {
5467 *status = (_ret != AVERROR_EOF ? DECODER_STATUS::DEC_ERROR : DECODER_STATUS::DEC_EOF); // If _ret == AVERROR_EOF, simply signal EOF
5468 return _ret;
5469 }
5470
5471 return 0;
5472}
5473
5475{
5477 {
5478 // No current seek frame, check if new seek frame was stacked.
5479 {
5480 std::lock_guard<std::recursive_mutex> lock_seek_to_fifo_mutex(m_seek_to_fifo_mutex);
5481
5482 while (!m_seek_to_fifo.empty())
5483 {
5484 uint32_t frame_no = m_seek_to_fifo.front();
5485 m_seek_to_fifo.pop();
5486
5487 if (!m_buffer->have_frame(frame_no))
5488 {
5489 // Frame not yet decoded, so skip to it.
5490 m_last_seek_frame_no = frame_no;
5491 break;
5492 }
5493 }
5494 }
5495
5497 {
5498 int ret = 0;
5499
5500 // The first frame that FFmpeg API returns after av_seek_frame is wrong (the last frame before seek).
5501 // We are unable to detect that because the pts seems correct (the one that we requested).
5502 // So we position before the frame requested, and simply throw the first away.
5503
5504 //#define PRESCAN_FRAMES 3
5505 uint32_t seek_frame_no = m_last_seek_frame_no.exchange(0);
5506#ifdef PRESCAN_FRAMES
5507 if (seek_frame_no > PRESCAN_FRAMES)
5508 {
5509 seek_frame_no -= PRESCAN_FRAMES;
5510 //m_skip_next_frame = true; /**< @todo Take deinterlace into account */
5511 }
5512 else
5513 {
5514 seek_frame_no = 1;
5515 }
5516
5517#endif
5518 ret = skip_decoded_frames(seek_frame_no, true);
5519 if (ret < 0)
5520 {
5521 return ret;
5522 }
5523 }
5524 }
5525 return 0;
5526}
5527
5529{
5530 bool opened = false;
5531
5532 encode_finish();
5533
5534 // Go to next requested segment...
5535 uint32_t next_segment = m_current_segment + 1;
5536
5537 // ...or process any stacked seek requests.
5538 while (!m_seek_to_fifo.empty())
5539 {
5540 uint32_t segment_no = m_seek_to_fifo.front();
5541 m_seek_to_fifo.pop();
5542
5543 // No check if m_segment_duration == 0, values <= 0 not accepted
5544 // Cast is OK here, the result will always be small enough for an int32.
5545 uint32_t min_seek_segments = static_cast<uint32_t>(params.m_min_seek_time_diff / params.m_segment_duration);
5546
5547 if (min_seek_segments && segment_no >= next_segment && segment_no <= next_segment + min_seek_segments)
5548 {
5549 Logging::info(virtname(), "Discarding seek request to HLS segment no. %1, less than %2 seconds (%3 segments) away.", segment_no, params.m_min_seek_time_diff / AV_TIME_BASE, min_seek_segments);
5550 continue;
5551 }
5552
5553 if (!m_buffer->segment_exists(segment_no) || !m_buffer->tell(segment_no)) // NOT EXIST or NO DATA YET
5554 {
5555 int ret = 0;
5556
5557 m_reset_pts = FFMPEGFS_AUDIO | FFMPEGFS_VIDEO; // Note that we have to reset audio/video pts to the new position
5558 m_have_seeked = true; // Note that we have seeked, thus skipped frames. We need to start transcoding over to fill any gaps.
5559
5560 Logging::info(virtname(), "Performing seek request to HLS segment no. %1.", segment_no);
5561
5562 int64_t pos = (segment_no - 1) * params.m_segment_duration;
5563
5565 {
5566 int64_t vstream_pts = ffmpeg_rescale_q(pos, av_get_time_base_q(), m_in.m_video.m_stream->time_base);
5567
5568 if (m_in.m_video.m_stream->start_time != AV_NOPTS_VALUE)
5569 {
5570 vstream_pts += m_in.m_video.m_stream->start_time;
5571 }
5572
5573 ret = av_seek_frame(m_in.m_format_ctx, m_in.m_video.m_stream_idx, vstream_pts, AVSEEK_FLAG_BACKWARD);
5574 }
5576 {
5577 int64_t astream_pts = ffmpeg_rescale_q(pos, av_get_time_base_q(), m_in.m_audio.m_stream->time_base);
5578
5579 if (m_in.m_audio.m_stream->start_time != AV_NOPTS_VALUE)
5580 {
5581 astream_pts += m_in.m_audio.m_stream->start_time;
5582 }
5583
5584 ret = av_seek_frame(m_in.m_format_ctx, m_in.m_audio.m_stream_idx, astream_pts, AVSEEK_FLAG_BACKWARD);
5585 }
5586
5587 if (ret < 0)
5588 {
5589 Logging::error(virtname(), "Seek failed on input file (error '%1').", ffmpeg_geterror(ret).c_str());
5590 return ret;
5591 }
5592
5593 flush_buffers();
5594
5596
5597 purge_hls_fifo(); // We do not need the packets for the next frame, we start a new one at another position!
5598
5599 ret = open_output(m_buffer);
5600 if (ret < 0)
5601 {
5602 return ret;
5603 }
5604
5605 next_segment = segment_no;
5606
5607 opened = true;
5608
5609 break;
5610 }
5611
5612 Logging::info(virtname(), "Discarded seek request to HLS segment no. %1.", segment_no);
5613 }
5614
5615 // Set current segment
5616 m_current_segment = next_segment;
5618 m_insert_keyframe = false;
5619
5620 Logging::info(virtname(), "Starting HLS segment no. %1 of %2.", m_current_segment, m_virtualfile->get_segment_count());
5621
5623 {
5624 return AVERROR(errno);
5625 }
5626
5627 if (!opened)
5628 {
5629 int ret = 0;
5630
5631 // Process output file, already done by open_output() if file has been newly opened.
5632 ret = process_output();
5633 if (ret)
5634 {
5635 return ret;
5636 }
5637 }
5638
5639 // Flush delayed packets to disk, if any
5640 while (!m_hls_packet_fifo.empty())
5641 {
5642 int ret = 0;
5643 AVPacket *pkt = m_hls_packet_fifo.front();
5644 m_hls_packet_fifo.pop();
5645
5646 ret = av_write_frame(m_out.m_format_ctx, pkt);
5647
5648 if (ret < 0)
5649 {
5650 Logging::error(virtname(), "Could not write frame (error '%1').", ffmpeg_geterror(ret).c_str());
5651 return ret;
5652 }
5653
5654 av_packet_unref(pkt);
5655 }
5656 return 0;
5657}
5658
5659BITRATE FFmpeg_Transcoder::get_prores_bitrate(int width, int height, const AVRational &framerate, bool interleaved, PRORESLEVEL profile)
5660{
5661 unsigned int mindist;
5662 size_t match = UINT_MAX;
5663
5664 // Find best match resolution
5665 mindist = UINT_MAX;
5666 for (size_t i = 0; i < m_prores_bitrate.size(); i++)
5667 {
5668 unsigned int x = static_cast<unsigned int>(width - m_prores_bitrate[i].m_width);
5669 unsigned int y = static_cast<unsigned int>(height - m_prores_bitrate[i].m_height);
5670 unsigned int dist = (x * x) + (y * y);
5671
5672 if (dist < mindist)
5673 {
5674 mindist = dist;
5675 match = i;
5676 }
5677
5678 if (!dist)
5679 {
5680 // Exact match, won't find a better one.
5681 break;
5682 }
5683 }
5684
5685 if (match == UINT_MAX)
5686 {
5687 return 0;
5688 }
5689
5690 width = m_prores_bitrate[match].m_width;
5691 height = m_prores_bitrate[match].m_height;
5692
5693 // Find best match framerate
5694 double framerateX = av_q2d(framerate);
5695 mindist = UINT_MAX;
5696 for (size_t i = match; width == m_prores_bitrate[i].m_width && height == m_prores_bitrate[i].m_height; i++)
5697 {
5698 unsigned int dist = UINT_MAX;
5699 for (size_t j = 0; j < MAX_PRORES_FRAMERATE && m_prores_bitrate[i].m_framerate[j].m_framerate; j++)
5700 {
5701 unsigned int x = static_cast<unsigned int>(framerateX - m_prores_bitrate[i].m_framerate[j].m_framerate);
5702 unsigned int y = static_cast<unsigned int>(interleaved - m_prores_bitrate[i].m_framerate[j].m_interleaved);
5703
5704 dist = (x * x) + (y * y);
5705
5706 if (dist < mindist)
5707 {
5708 mindist = dist;
5709 match = i;
5710 }
5711
5712 if (!dist)
5713 {
5714 // Exact match, won't find a better one.
5715 break;
5716 }
5717 }
5718
5719 if (!dist)
5720 {
5721 // Exact match, won't find a better one.
5722 break;
5723 }
5724 }
5725
5726 if (match == UINT_MAX)
5727 {
5728 return 0;
5729 }
5730
5731 return m_prores_bitrate[match].m_bitrate[static_cast<size_t>(profile)] * (1000 * 1000);
5732}
5733
5734bool FFmpeg_Transcoder::audio_size(size_t *filesize, AVCodecID codec_id, BITRATE bit_rate, int64_t duration, int channels, int sample_rate, AVSampleFormat sample_format)
5735{
5736 BITRATE output_audio_bit_rate;
5737 int output_sample_rate;
5738 bool success = true;
5739
5740 get_output_bit_rate(bit_rate, params.m_audiobitrate, &output_audio_bit_rate);
5741 get_output_sample_rate(sample_rate, params.m_audiosamplerate, &output_sample_rate);
5742
5743 switch (codec_id)
5744 {
5745 case AV_CODEC_ID_AAC:
5746 {
5747 // Try to predict the size of the AAC stream (this is fairly accurate, sometimes a bit larger, sometimes a bit too small
5748 *filesize += static_cast<size_t>(duration * output_audio_bit_rate / (8LL * AV_TIME_BASE));
5749 *filesize = static_cast<size_t>(1025 * (*filesize) / 1000); // add overhead (empirically determined value)
5750 break;
5751 }
5752 case AV_CODEC_ID_MP3:
5753 {
5754 // Kbps = bits per second / 8 = Bytes per second x 60 seconds = Bytes per minute x 60 minutes = Bytes per hour
5755 // This is the sum of the size of
5756 // ID3v2, ID3v1, and raw MP3 data. This is theoretically only approximate
5757 // but in practice gives excellent answers, usually exactly correct.
5758 // Cast to 64-bit int to avoid overflow.
5759
5760 *filesize += static_cast<size_t>(duration * output_audio_bit_rate / (8LL * AV_TIME_BASE)) + ID3V1_TAG_LENGTH;
5761 break;
5762 }
5763 case AV_CODEC_ID_PCM_U8:
5764 case AV_CODEC_ID_PCM_S8:
5765 {
5766 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_U8); // Unsigned/signed 8 have the same width
5767
5768 // File size:
5769 // file duration * sample rate (HZ) * channels * bytes per sample
5770 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5771 // The real size of the list header is unkown as we don't know the contents (meta tags)
5772 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5773 break;
5774 }
5775 case AV_CODEC_ID_PCM_S8_PLANAR:
5776 {
5777 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_U8P);
5778
5779 // File size:
5780 // file duration * sample rate (HZ) * channels * bytes per sample
5781 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5782 // The real size of the list header is unkown as we don't know the contents (meta tags)
5783 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5784 break;
5785 }
5786 case AV_CODEC_ID_PCM_U16LE:
5787 case AV_CODEC_ID_PCM_U16BE:
5788 case AV_CODEC_ID_PCM_S16LE:
5789 case AV_CODEC_ID_PCM_S16BE:
5790 {
5791 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); // Unsigned/signed 16 have the same width
5792
5793 // File size:
5794 // file duration * sample rate (HZ) * channels * bytes per sample
5795 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5796 // The real size of the list header is unkown as we don't know the contents (meta tags)
5797 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5798 break;
5799 }
5800 case AV_CODEC_ID_PCM_S16LE_PLANAR:
5801 case AV_CODEC_ID_PCM_S16BE_PLANAR:
5802 {
5803 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16P); // Unsigned/signed 16 have the same width
5804
5805 // File size:
5806 // file duration * sample rate (HZ) * channels * bytes per sample
5807 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5808 // The real size of the list header is unkown as we don't know the contents (meta tags)
5809 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5810 break;
5811 }
5812 case AV_CODEC_ID_PCM_U24LE: // U/S24 uses U/S32 storage
5813 case AV_CODEC_ID_PCM_U24BE:
5814 case AV_CODEC_ID_PCM_S24LE:
5815 case AV_CODEC_ID_PCM_S24BE:
5816 case AV_CODEC_ID_PCM_U32LE:
5817 case AV_CODEC_ID_PCM_U32BE:
5818 case AV_CODEC_ID_PCM_S32LE:
5819 case AV_CODEC_ID_PCM_S32BE:
5820 {
5821 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S32); // Unsigned/signed 32 have the same width
5822
5823 // File size:
5824 // file duration * sample rate (HZ) * channels * bytes per sample
5825 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5826 // The real size of the list header is unkown as we don't know the contents (meta tags)
5827 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5828 break;
5829 }
5830 case AV_CODEC_ID_PCM_S24LE_PLANAR: // S24 uses S32 storage
5831 case AV_CODEC_ID_PCM_S32LE_PLANAR:
5832 {
5833 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S32P);
5834
5835 // File size:
5836 // file duration * sample rate (HZ) * channels * bytes per sample
5837 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5838 // The real size of the list header is unkown as we don't know the contents (meta tags)
5839 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5840 break;
5841 }
5842 case AV_CODEC_ID_PCM_S64LE:
5843 case AV_CODEC_ID_PCM_S64BE:
5844 {
5845 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S64);
5846
5847 // File size:
5848 // file duration * sample rate (HZ) * channels * bytes per sample
5849 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5850 // The real size of the list header is unkown as we don't know the contents (meta tags)
5851 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5852 break;
5853 }
5854 case AV_CODEC_ID_PCM_F16LE:
5855 case AV_CODEC_ID_PCM_F24LE:
5856 case AV_CODEC_ID_PCM_F32BE:
5857 case AV_CODEC_ID_PCM_F32LE:
5858 case AV_CODEC_ID_PCM_F64BE:
5859 case AV_CODEC_ID_PCM_F64LE:
5860 {
5861 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT);
5862
5863 // File size:
5864 // file duration * sample rate (HZ) * channels * bytes per sample
5865 // + WAV_HEADER + DATA_HEADER + (with FFMpeg always) LIST_HEADER
5866 // The real size of the list header is unkown as we don't know the contents (meta tags)
5867 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5868 break;
5869 }
5870 case AV_CODEC_ID_VORBIS:
5871 {
5872 // Kbps = bits per second / 8 = Bytes per second x 60 seconds = Bytes per minute x 60 minutes = Bytes per hour
5873 *filesize += static_cast<size_t>(duration * output_audio_bit_rate / (8LL * AV_TIME_BASE));
5874 *filesize = static_cast<size_t>(900 * (*filesize) / 1000); // OGG files seem to be rather smaller than expected (empirically determined value)
5875 break;
5876 }
5877 case AV_CODEC_ID_OPUS:
5878 {
5879 // Kbps = bits per second / 8 = Bytes per second x 60 seconds = Bytes per minute x 60 minutes = Bytes per hour
5880 *filesize += static_cast<size_t>(duration * output_audio_bit_rate / (8LL * AV_TIME_BASE));
5881 *filesize = static_cast<size_t>(1020 * (*filesize) / 1000); // add overhead (empirically determined value)
5882 break;
5883 }
5884 case AV_CODEC_ID_ALAC:
5885 {
5886 int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
5887
5888 // File size:
5889 // Apple Lossless Audio Coding promises a compression rate of 60-70%. The actual result ranges
5890 // between 30 and over 50%, heavily depending on the input.
5891 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5892 *filesize = static_cast<size_t>(620 * (*filesize) / 1000); // Estimate 38% compression rate (empirically determined value)
5893 break;
5894 }
5895 case AV_CODEC_ID_AC3:
5896 {
5897 // Kbps = bits per second / 8 = Bytes per second x 60 seconds = Bytes per minute x 60 minutes = Bytes per hour
5898 *filesize += static_cast<size_t>(duration * output_audio_bit_rate / (8LL * AV_TIME_BASE));
5899 *filesize = static_cast<size_t>(1025 * (*filesize) / 1000); // add overhead (empirically determined value)
5900 break;
5901 }
5902 case AV_CODEC_ID_FLAC:
5903 {
5904 int bytes_per_sample = av_get_bytes_per_sample(sample_format != AV_SAMPLE_FMT_NONE ? sample_format : AV_SAMPLE_FMT_S16);
5905
5906 // File size:
5907 // file duration * sample rate (HZ) * channels * bytes per sample
5908 // We do not add the overhead for headers, as this is an estimation and not exact anyways.
5909 *filesize += static_cast<size_t>(duration * sample_rate * (channels >= 2 ? 2 : 1) * bytes_per_sample / AV_TIME_BASE);
5910 *filesize = static_cast<size_t>(600 * (*filesize) / 1000); // Estimate 40% compression rate (empirically determined value)
5911 break;
5912 }
5913 case AV_CODEC_ID_NONE:
5914 {
5915 break;
5916 }
5917 default:
5918 {
5919 success = false;
5920 break;
5921 }
5922 }
5923 return success;
5924}
5925
5926bool FFmpeg_Transcoder::video_size(size_t *filesize, AVCodecID codec_id, BITRATE bit_rate, int64_t duration, int width, int height, bool interleaved, const AVRational &framerate)
5927{
5928 BITRATE out_video_bit_rate;
5929 bool success = true;
5930
5931 get_output_bit_rate(bit_rate, params.m_videobitrate, &out_video_bit_rate);
5932
5933 switch (codec_id)
5934 {
5935 case AV_CODEC_ID_MPEG1VIDEO:
5936 {
5937 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5938 *filesize = static_cast<size_t>(1020 * (*filesize) / 1000); // add overhead
5939 break;
5940 }
5941 case AV_CODEC_ID_MPEG2VIDEO:
5942 {
5943 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5944 *filesize = static_cast<size_t>(1020 * (*filesize) / 1000); // add overhead
5945 break;
5946 }
5947 case AV_CODEC_ID_H264:
5948 {
5949 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5950 *filesize = static_cast<size_t>(1050 * (*filesize) / 1000); // add overhead
5951 break;
5952 }
5953 case AV_CODEC_ID_H265:
5954 {
5955 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5956 *filesize = static_cast<size_t>(1250 * (*filesize) / 1000); // add overhead
5957 break;
5958 }
5959 case AV_CODEC_ID_THEORA:
5960 {
5961 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5962 *filesize = static_cast<size_t>(1025 * (*filesize) / 1000); // add overhead
5963 break;
5964 }
5965 case AV_CODEC_ID_VP8:
5966 {
5967 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5968 *filesize = static_cast<size_t>(1020 * (*filesize) / 1000); // add overhead
5969 break;
5970 }
5971 case AV_CODEC_ID_VP9:
5972 {
5973 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5974 *filesize = static_cast<size_t>(1450 * (*filesize) / 1000); // add overhead
5975 break;
5976 }
5977 case AV_CODEC_ID_AV1:
5978 {
5979 *filesize += static_cast<size_t>(duration * out_video_bit_rate / (8LL * AV_TIME_BASE));
5980 //*filesize = static_cast<size_t>(1150 * (*filesize) / 1000); // add overhead
5981 break;
5982 }
5983 case AV_CODEC_ID_PRORES:
5984 {
5985 *filesize += static_cast<size_t>(duration * get_prores_bitrate(width, height, framerate, interleaved, params.m_level) / (8LL * AV_TIME_BASE));
5986 break;
5987 }
5988 case AV_CODEC_ID_PNG:
5989 case AV_CODEC_ID_BMP:
5990 case AV_CODEC_ID_MJPEG:
5991 {
5992 // Max. file size = (pixel dimensions x bit depth) / 8 for an uncompressed BMP,
5993 // more than sufficient for JPG/PNG as they should never get this large.
5994 *filesize += static_cast<size_t>(width * height * 24 / 8); // Get the max. size
5995 break;
5996 }
5997 case AV_CODEC_ID_NONE:
5998 {
5999 break;
6000 }
6001 default:
6002 {
6003 success = false;
6004 break;
6005 }
6006 }
6007 return success;
6008}
6009
6010bool FFmpeg_Transcoder::total_overhead(size_t *filesize, FILETYPE filetype)
6011{
6012 bool success = true;
6013
6014 switch (filetype)
6015 {
6016 //
6017 // Audio only
6018 //
6019 case FILETYPE::MP3:
6020 {
6021 // The FFmpeg API always adds an IDv2 header, size of which is unknown and
6022 // really hard to determine. So we simply add something reasonable (empirically determined value).
6023 *filesize += 250000;
6024 break;
6025 }
6026 case FILETYPE::WAV:
6027 {
6028 // This could actually precise, but yet the FFmpeg API always adds an IDv2 header,
6029 // size of which is unknown and really hard to determine. The header is small, ~30 bytes,
6030 // so we ignore that deliberatly.
6031 *filesize += sizeof(WAV_HEADER) + sizeof(WAV_LIST_HEADER) + sizeof(WAV_DATA_HEADER);
6032 break;
6033 }
6034 case FILETYPE::AIFF:
6035 {
6036 // These two "chunks" will always be there, others may be there, may be not. Their
6037 // size is hard to precalculate and small (~100 bytes), so we disregard the rest.
6038 *filesize += sizeof(AIFF_FORMCHUNK) + sizeof(AIFF_COMMONCHUNK);
6039 break;
6040 }
6041 case FILETYPE::OPUS:
6042 case FILETYPE::ALAC:
6043 case FILETYPE::FLAC:
6044 {
6045 break;
6046 }
6047 //
6048 // Video
6049 //
6050 case FILETYPE::TS:
6051 case FILETYPE::HLS:
6052 {
6053 *filesize += 1600000; // empirically determined value
6054 break;
6055 }
6056 case FILETYPE::MP4:
6057 case FILETYPE::OGG:
6058 case FILETYPE::WEBM:
6059 case FILETYPE::MOV:
6060 case FILETYPE::PRORES:
6061 case FILETYPE::MKV:
6062 {
6063 break;
6064 }
6065 //
6066 // Stills
6067 //
6068 case FILETYPE::PNG:
6069 case FILETYPE::JPG:
6070 case FILETYPE::BMP:
6071 {
6072 break;
6073 }
6074 //
6075 // Invalid
6076 //
6077 case FILETYPE::UNKNOWN:
6078 {
6079 success = false;
6080 break;
6081 }
6082 }
6083
6084 return success;
6085}
6086
6088{
6089 if (m_in.m_format_ctx == nullptr)
6090 {
6091 return 0;
6092 }
6093
6094 if (m_current_format == nullptr)
6095 {
6096 // Should ever happen, but better check this to avoid crashes.
6097 return 0;
6098 }
6099
6100 size_t filesize = 0;
6101
6102 int64_t file_duration = m_in.m_format_ctx->duration != AV_NOPTS_VALUE ? m_in.m_format_ctx->duration : 0;
6103 BITRATE input_audio_bit_rate = 0;
6104 int input_sample_rate = 0;
6105 BITRATE input_video_bit_rate = 0;
6106
6107 if (m_fileio->duration() != AV_NOPTS_VALUE)
6108 {
6109 file_duration = m_fileio->duration();
6110 }
6111
6113 {
6114 input_sample_rate = m_in.m_audio.m_stream->codecpar->sample_rate;
6115 input_audio_bit_rate = (m_in.m_audio.m_stream->codecpar->bit_rate != 0) ? m_in.m_audio.m_stream->codecpar->bit_rate : m_in.m_format_ctx->bit_rate;
6116 }
6117
6119 {
6120 input_video_bit_rate = (m_in.m_video.m_stream->codecpar->bit_rate != 0) ? m_in.m_video.m_stream->codecpar->bit_rate : m_in.m_format_ctx->bit_rate;
6121 }
6122
6123 if (input_audio_bit_rate)
6124 {
6125 int channels = get_channels(m_in.m_audio.m_codec_ctx.get());
6126
6127 if (!audio_size(&filesize, m_current_format->audio_codec(), input_audio_bit_rate, file_duration, channels, input_sample_rate, m_cur_sample_fmt))
6128 {
6129 Logging::warning(filename(), "Unsupported audio codec '%1' for format %2.", get_codec_name(m_current_format->audio_codec()), m_current_format->desttype().c_str());
6130 }
6131 }
6132
6133 if (input_video_bit_rate)
6134 {
6135 if (m_is_video)
6136 {
6137 int width = m_in.m_video.m_stream->codecpar->width;
6138 int height = m_in.m_video.m_stream->codecpar->height;
6139 bool interleaved = params.m_deinterlace ? false : (m_in.m_video.m_stream->codecpar->field_order != AV_FIELD_PROGRESSIVE); // Deinterlace only if source is interlaced
6140 AVRational framerate = m_in.m_video.m_stream->avg_frame_rate;
6141
6142 if (!video_size(&filesize, m_current_format->video_codec(), input_video_bit_rate, file_duration, width, height, interleaved, framerate))
6143 {
6144 Logging::warning(filename(), "Unsupported video codec '%1' for format %2.", get_codec_name(m_current_format->video_codec()), m_current_format->desttype().c_str());
6145 }
6146 }
6147 // else /** @todo Feature #2260: Add picture size */
6148 // {
6149 // }
6150 }
6151
6152 // Support #2654: Test Code
6153 // add total overhead
6155
6156 return filesize;
6157}
6158
6160{
6161 return SAFE_VALUE(m_virtualfile, m_duration, 0);
6162}
6163
6165{
6166 return SAFE_VALUE(m_virtualfile, m_predicted_size, 0);
6167}
6168
6170{
6171 return SAFE_VALUE(m_virtualfile, m_video_frame_count, 0);
6172}
6173
6175{
6176 return SAFE_VALUE(m_virtualfile, get_segment_count(), 0);
6177}
6178
6180{
6181 int ret = 0;
6182
6183 if (!is_frameset())
6184 {
6185 // If not a frame set, write trailer
6186
6187 // Write the trailer of the output file container.
6189 }
6190
6191 if (is_hls())
6192 {
6194
6195 // Get segment VIRTUALFILE object
6197 LPVIRTUALFILE virtualfile = find_file(seg_filename);
6198
6199 if (virtualfile != nullptr)
6200 {
6202
6203 stat_set_size(&virtualfile->m_st, virtualfile->m_predicted_size);
6204 }
6205 }
6206 else //if (m_virtualfile->m_flags & VIRTUALFLAG_CUESHEET)
6207 {
6208 // Save actual result size of the file
6210 }
6211
6212 return ret;
6213}
6214
6216{
6217 return &m_out.m_id3v1;
6218}
6219
6220int FFmpeg_Transcoder::input_read(void * opaque, unsigned char * data, int size)
6221{
6222 FileIO * io = static_cast<FileIO *>(opaque);
6223
6224 if (io == nullptr)
6225 {
6226 Logging::error(nullptr, "input_read(): Internal error: FileIO is NULL!");
6227 return AVERROR(EINVAL);
6228 }
6229
6230 if (io->eof())
6231 {
6232 // At EOF
6233 return AVERROR_EOF;
6234 }
6235
6236 int read = static_cast<int>(io->readio(reinterpret_cast<char *>(data), static_cast<size_t>(size)));
6237
6238 if (read != size && io->error())
6239 {
6240 // Read failed
6241 return AVERROR(io->error());
6242 }
6243
6244 return read;
6245}
6246
6247#if LAVF_WRITEPACKET_CONST
6248int FFmpeg_Transcoder::output_write(void * opaque, const uint8_t * data, int size)
6249#else
6250int FFmpeg_Transcoder::output_write(void * opaque, unsigned char * data, int size)
6251#endif
6252{
6253 Buffer * buffer = static_cast<Buffer *>(opaque);
6254
6255 if (buffer == nullptr)
6256 {
6257 Logging::error(nullptr, "input_write(): Internal error: FileIO is NULL!");
6258 return AVERROR(EINVAL);
6259 }
6260
6261#if LAVF_WRITEPACKET_CONST
6262 int written = static_cast<int>(buffer->writeio(data, static_cast<size_t>(size)));
6263#else
6264 int written = static_cast<int>(buffer->writeio(static_cast<const uint8_t*>(data), static_cast<size_t>(size)));
6265#endif
6266 if (written != size)
6267 {
6268 // Write error
6269 return (AVERROR(errno));
6270 }
6271 return written;
6272}
6273
6274int64_t FFmpeg_Transcoder::seek(void * opaque, int64_t offset, int whence)
6275{
6276 FileIO * io = static_cast<FileIO *>(opaque);
6277 int64_t res_offset = 0;
6278
6279 if (io == nullptr)
6280 {
6281 Logging::error(nullptr, "seek(): Internal error: FileIO is NULL!");
6282 return AVERROR(EINVAL);
6283 }
6284
6285 if (whence & AVSEEK_SIZE)
6286 {
6287 // Return file size
6288 res_offset = static_cast<int64_t>(io->size());
6289 }
6290 else
6291 {
6292 whence &= ~(AVSEEK_SIZE | AVSEEK_FORCE);
6293
6294 if (!io->seek(offset, whence))
6295 {
6296 // OK: Return position
6297 res_offset = offset;
6298 }
6299 else
6300 {
6301 // Error
6302 res_offset = AVERROR(errno);
6303 }
6304 }
6305
6306 return res_offset;
6307}
6308
6310{
6312 {
6313 swr_free(&m_audio_resample_ctx);
6314 m_audio_resample_ctx = nullptr;
6315 return true;
6316 }
6317
6318 return false;
6319}
6320
6322{
6323 int audio_samples_left = 0;
6324
6325 if (m_audio_fifo != nullptr)
6326 {
6327 audio_samples_left = av_audio_fifo_size(m_audio_fifo);
6328 av_audio_fifo_free(m_audio_fifo);
6329 m_audio_fifo = nullptr;
6330 }
6331
6332 return audio_samples_left;
6333}
6334
6336{
6337 size_t frames_left = m_frame_map.size();
6338
6339 m_frame_map.clear();
6340
6341 return frames_left;
6342}
6343
6345{
6346 size_t hls_packets_left = m_hls_packet_fifo.size();
6347
6348 while (!m_hls_packet_fifo.empty())
6349 {
6350 AVPacket *pkt = m_hls_packet_fifo.front();
6351 m_hls_packet_fifo.pop();
6352
6353 av_packet_unref(pkt);
6354 }
6355
6356 return hls_packets_left;
6357}
6358
6360{
6361 std::string outfile;
6362 int audio_samples_left = purge_audio_fifo();
6363 size_t frames_left = purge_multiframe_map();
6364 size_t hls_packets_left = purge_hls_fifo();
6365
6366 if (m_out.m_format_ctx != nullptr && m_out.m_format_ctx->url != nullptr)
6367 {
6368 outfile = m_out.m_format_ctx->url;
6369 }
6370 else if (m_virtualfile != nullptr)
6371 {
6372 outfile = m_virtualfile->m_virtfile;
6373 }
6374
6375 const char *p = outfile.empty() ? nullptr : outfile.c_str();
6376 if (audio_samples_left)
6377 {
6378 Logging::warning(p, "%1 audio samples left in buffer and not written to target file!", audio_samples_left);
6379 }
6380
6381 if (frames_left)
6382 {
6383 Logging::warning(p, "%1 frames left in buffer and not written to target file!", frames_left);
6384 }
6385
6386 if (hls_packets_left)
6387 {
6388 Logging::warning(p, "%1 HLS packets left in buffer and not written to target file!", hls_packets_left);
6389 }
6390}
6391
6393{
6394 bool closed = false;
6395
6396 purge();
6397
6399
6400 sws_freeContext(m_sws_ctx);
6401 m_sws_ctx = nullptr;
6402
6403 // Close output file
6406
6407 m_out.m_album_art.clear();
6408 m_out.m_subtitle.clear();
6409
6410 if (m_out.m_format_ctx != nullptr)
6411 {
6412 closed = true;
6413
6414 if (m_out.m_format_ctx->pb != nullptr)
6415 {
6416 // 2017-09-01 - xxxxxxx - lavf 57.80.100 / 57.11.0 - avio.h
6417 // Add avio_context_free(). From now on it must be used for freeing AVIOContext.
6418#if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 80, 0))
6419 av_freep(&m_out.m_format_ctx->pb->buffer);
6420 avio_context_free(&m_out.m_format_ctx->pb);
6421#else
6422 av_freep(m_out.m_format_ctx->pb);
6423#endif
6424 m_out.m_format_ctx->pb = nullptr;
6425 }
6426
6427 avformat_free_context(m_out.m_format_ctx);
6428
6429 m_out.m_format_ctx = nullptr;
6430 }
6431
6432 return closed;
6433}
6434
6436{
6437 bool closed = false;
6438
6439 m_in.m_audio.reset();
6440 m_in.m_video.reset();
6441
6442 m_in.m_album_art.clear();
6443 m_in.m_subtitle.clear();
6444
6445 if (m_in.m_format_ctx != nullptr)
6446 {
6447 closed = true;
6448
6449 if (m_fileio.use_count() <= 1 && m_fileio != nullptr)
6450 {
6451 m_fileio->closeio();
6452 }
6453 m_fileio.reset();
6454
6455 if (m_in.m_format_ctx->pb != nullptr)
6456 {
6457 // 2017-09-01 - xxxxxxx - lavf 57.80.100 / 57.11.0 - avio.h
6458 // Add avio_context_free(). From now on it must be used for freeing AVIOContext.
6459#if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 80, 0))
6460 avio_context_free(&m_in.m_format_ctx->pb);
6461#else
6462 av_freep(m_in.m_format_ctx->pb);
6463#endif
6464 m_in.m_format_ctx->pb = nullptr;
6465 }
6466
6467 avformat_close_input(&m_in.m_format_ctx);
6468 m_in.m_format_ctx = nullptr;
6469 }
6470
6471 free_filters();
6472
6473 return closed;
6474}
6475
6477{
6478 bool closed = false;
6479
6480 // Close input file
6481 closed |= close_input_file();
6482
6483 // Close output file
6484 closed |= close_output_file();
6485
6486 // Free hardware device contexts if open
6489
6490 // Closed anything (anything had been open to be closed in the first place)...
6491 if (closed)
6492 {
6493 Logging::trace(nullptr, "FFmpeg transcoder closed.");
6494 }
6495}
6496
6498{
6499 return (m_virtualfile != nullptr ? m_virtualfile->m_origfile.c_str() : "");
6500}
6501
6503{
6504 return (m_virtualfile != nullptr ? m_virtualfile->m_destfile.c_str() : "");
6505}
6506
6508{
6509 return (m_virtualfile != nullptr ? m_virtualfile->m_virtfile.c_str() : "");
6510}
6511
6512// create
6513int FFmpeg_Transcoder::init_deinterlace_filters(AVCodecContext *codec_ctx, AVPixelFormat pix_fmt, const AVRational & avg_frame_rate, const AVRational & time_base)
6514{
6515 const AVFilter * buffer_src = avfilter_get_by_name("buffer");
6516 const AVFilter * buffer_sink = avfilter_get_by_name("buffersink");
6517 AVFilterInOut * outputs = avfilter_inout_alloc();
6518 AVFilterInOut * inputs = avfilter_inout_alloc();
6519 //enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
6520 int ret = 0;
6521
6522 m_buffer_sink_context = nullptr;
6523 m_buffer_source_context = nullptr;
6524 m_filter_graph = nullptr;
6525
6526 try
6527 {
6528 if (!avg_frame_rate.den && !avg_frame_rate.num)
6529 {
6530 // No framerate, so this video "stream" has only one picture
6531 throw static_cast<int>(AVERROR(EINVAL));
6532 }
6533
6534 m_filter_graph = avfilter_graph_alloc();
6535
6536 if (outputs == nullptr || inputs == nullptr || m_filter_graph == nullptr)
6537 {
6538 throw static_cast<int>(AVERROR(ENOMEM));
6539 }
6540
6541 // buffer video source: the decoded frames from the decoder will be inserted here.
6542 std::string args;
6543
6544 strsprintf(&args, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
6545 codec_ctx->width, codec_ctx->height, pix_fmt,
6546 time_base.num, time_base.den,
6547 codec_ctx->sample_aspect_ratio.num, FFMAX(codec_ctx->sample_aspect_ratio.den, 1));
6548
6549 //AVRational fr = av_guess_frame_rate(m_m_out.m_format_ctx, m_pVideoStream, nullptr);
6550 //if (fr.num && fr.den)
6551 //{
6552 // av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":framerate=%d/%d", fr.num, fr.den);
6553 //}
6554 //
6555 //args.snprintf("%d:%d:%d:%d:%d", m_pCodecContext->width, m_pCodecContext->height, m_pCodecContext->format, 0, 0); // 0, 0 ok?
6556
6557 ret = avfilter_graph_create_filter(&m_buffer_source_context, buffer_src, "in", args.c_str(), nullptr, m_filter_graph);
6558 if (ret < 0)
6559 {
6560 Logging::error(virtname(), "Cannot create buffer source (error '%1').", ffmpeg_geterror(ret).c_str());
6561 throw ret;
6562 }
6563
6564 //av_opt_set(m_pBufferSourceContext, "thread_type", "slice", AV_OPT_SEARCH_CHILDREN);
6565 //av_opt_set_int(m_pBufferSourceContext, "threads", FFMAX(1, av_cpu_count()), AV_OPT_SEARCH_CHILDREN);
6566 //av_opt_set_int(m_pBufferSourceContext, "threads", 16, AV_OPT_SEARCH_CHILDREN);
6567
6568 // buffer video sink: to terminate the filter chain.
6569
6570 std::array<enum AVPixelFormat, 3> pixel_fmts;
6571
6572 pixel_fmts[0] = pix_fmt;
6573 pixel_fmts[1] = AV_PIX_FMT_NONE;
6574
6575 ret = avfilter_graph_create_filter(&m_buffer_sink_context, buffer_sink, "out", nullptr, nullptr, m_filter_graph);
6576
6577 if (ret < 0)
6578 {
6579 Logging::error(virtname(), "Cannot create buffer sink (error '%1').", ffmpeg_geterror(ret).c_str());
6580 throw ret;
6581 }
6582
6583 // Cannot change FFmpeg's API, so we hide this warning
6584#pragma GCC diagnostic push
6585#pragma GCC diagnostic ignored "-Wconversion"
6586#pragma GCC diagnostic ignored "-Wsign-conversion"
6587 ret = av_opt_set_int_list(m_buffer_sink_context, "pix_fmts", pixel_fmts.data(), AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
6588#pragma GCC diagnostic pop
6589
6590 if (ret < 0)
6591 {
6592 Logging::error(nullptr, "Cannot set output pixel format (error '%1').", ffmpeg_geterror(ret).c_str());
6593 throw ret;
6594 }
6595
6596 // Endpoints for the filter graph.
6597 outputs->name = av_strdup("in");
6598 outputs->filter_ctx = m_buffer_source_context;
6599 outputs->pad_idx = 0;
6600 outputs->next = nullptr;
6601 inputs->name = av_strdup("out");
6602 inputs->filter_ctx = m_buffer_sink_context;
6603 inputs->pad_idx = 0;
6604 inputs->next = nullptr;
6605
6606 // args "null" passthrough (dummy) filter for video
6607 // args "null" passthrough (dummy) filter for audio
6608
6609 // https://stackoverflow.com/questions/31163120/c-applying-filter-in-ffmpeg
6610 const char * filters;
6611 //filters = "yadif=mode=send_frame:parity=auto:deint=interlaced";
6612 filters = "yadif=mode=send_frame:parity=auto:deint=all";
6613 //filters = "yadif=0:-1:0";
6614 //filters = "bwdif=mode=send_frame:parity=auto:deint=all";
6615 //filters = "kerndeint=thresh=10:map=0:order=0:sharp=1:twoway=1";
6616 //filters = "zoompan=z='min(max(zoom,pzoom)+0.0015,1.5)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'";
6617
6618 // vaapi_deinterlace=rate=field
6619 // format=nv12,hwupload,deinterlace_vaapi,hwdownload,format=nv12
6620 // deinterlace_vaapi,scale_vaapi=w=1280:h=720,hwdownload,format=nv12
6621
6622 ret = avfilter_graph_parse_ptr(m_filter_graph, filters, &inputs, &outputs, nullptr);
6623 if (ret < 0)
6624 {
6625 Logging::error(virtname(), "avfilter_graph_parse_ptr failed (error '%1').", ffmpeg_geterror(ret).c_str());
6626 throw ret;
6627 }
6628
6629 ret = avfilter_graph_config(m_filter_graph, nullptr);
6630 if (ret < 0)
6631 {
6632 Logging::error(virtname(), "avfilter_graph_config failed (error '%1').", ffmpeg_geterror(ret).c_str());
6633 throw ret;
6634 }
6635
6636 Logging::debug(virtname(), "Deinterlacing initialised with filters '%1'.", filters);
6637 }
6638 catch (int _ret)
6639 {
6640 ret = _ret;
6641 }
6642
6643 if (inputs != nullptr)
6644 {
6645 avfilter_inout_free(&inputs);
6646 }
6647 if (outputs != nullptr)
6648 {
6649 avfilter_inout_free(&outputs);
6650 }
6651
6652 return ret;
6653}
6654
6656{
6657 ret = 0;
6658
6659 if (m_buffer_source_context != nullptr)
6660 {
6661 try
6662 {
6663 FFmpeg_Frame filterframe(srcframe->m_stream_idx);
6664
6665 ret = filterframe.res();
6666 if (ret < 0)
6667 {
6668 Logging::error(virtname(), "Unable to allocate filter frame (error '%1').", ffmpeg_geterror(ret).c_str());
6669 throw ret;
6670 }
6671
6672 // push the decoded frame into the filtergraph
6673 ret = av_buffersrc_add_frame_flags(m_buffer_source_context, *srcframe, AV_BUFFERSRC_FLAG_KEEP_REF);
6674 if (ret < 0)
6675 {
6676 Logging::warning(virtname(), "Error while feeding the frame to filtergraph (error '%1').", ffmpeg_geterror(ret).c_str());
6677 throw ret;
6678 }
6679
6680 // pull filtered frames from the filtergraph
6681 ret = av_buffersink_get_frame(m_buffer_sink_context, filterframe);
6682 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
6683 {
6684 // Not an error, go on
6685 ret = 0;
6686 }
6687 else if (ret < 0)
6688 {
6689 Logging::error(virtname(), "Error while getting frame from filtergraph (error '%1').", ffmpeg_geterror(ret).c_str());
6690 throw ret;
6691 }
6692 else
6693 {
6694 // All OK; copy filtered frame and unref original
6695 filterframe->pts = (*srcframe)->pts;
6696 filterframe->best_effort_timestamp = (*srcframe)->best_effort_timestamp;
6697
6698 *srcframe = filterframe;
6699 }
6700 }
6701 catch (int _ret)
6702 {
6703 ret = _ret;
6704 }
6705 }
6706
6707 return ret;
6708}
6709
6710// free
6711
6713{
6714 if (m_buffer_sink_context != nullptr)
6715 {
6716 avfilter_free(m_buffer_sink_context);
6717 m_buffer_sink_context = nullptr;
6718 }
6719
6720 if (m_buffer_source_context != nullptr)
6721 {
6722 avfilter_free(m_buffer_source_context);
6723 m_buffer_source_context = nullptr;
6724 }
6725
6726 if (m_filter_graph != nullptr)
6727 {
6728 avfilter_graph_free(&m_filter_graph);
6729 m_filter_graph = nullptr;
6730 }
6731}
6732
6734{
6735 if (frame_no > 0 && frame_no <= video_frame_count())
6736 {
6737 std::lock_guard<std::recursive_mutex> lock_seek_to_fifo_mutex(m_seek_to_fifo_mutex);
6738 m_seek_to_fifo.push(frame_no); // Seek to this frame next decoding operation
6739 return 0;
6740 }
6741 else
6742 {
6743 errno = EINVAL;
6744 Logging::error(virtname(), "stack_seek_frame() failed: Frame %1 was requested, but is out of range (1...%2)", frame_no, video_frame_count() + 1);
6745 return AVERROR(EINVAL);
6746 }
6747}
6748
6750{
6751 if (segment_no > 0 && segment_no <= segment_count())
6752 {
6753 std::lock_guard<std::recursive_mutex> lock_seek_to_fifo_mutex(m_seek_to_fifo_mutex);
6754 m_seek_to_fifo.push(segment_no); // Seek to this segment next decoding operation
6755 return 0;
6756 }
6757 else
6758 {
6759 errno = EINVAL;
6760 Logging::error(virtname(), "stack_seek() failed: Segment no. %1 was requested, but is out of range (1...%2)", segment_no, video_frame_count() + 1);
6761 return AVERROR(EINVAL);
6762 }
6763}
6764
6766{
6767 if (m_current_format == nullptr)
6768 {
6769 return false;
6770 }
6771 else
6772 {
6774 }
6775}
6776
6777
6779{
6780 if (m_current_format == nullptr)
6781 {
6782 return false;
6783 }
6784 else
6785 {
6786 return m_current_format->is_frameset();
6787 }
6788}
6789
6791{
6792 if (m_current_format == nullptr)
6793 {
6794 return false;
6795 }
6796 else
6797 {
6798 return m_current_format->is_hls();
6799 }
6800}
6801
6803{
6804 return m_have_seeked;
6805}
6806
6807enum AVPixelFormat FFmpeg_Transcoder::get_format_static(AVCodecContext *input_codec_ctx, const enum AVPixelFormat *pix_fmts)
6808{
6809 FFmpeg_Transcoder * pThis = static_cast<FFmpeg_Transcoder *>(input_codec_ctx->opaque);
6810 return pThis->get_format(input_codec_ctx, pix_fmts);
6811}
6812
6813enum AVPixelFormat FFmpeg_Transcoder::get_format(__attribute__((unused)) AVCodecContext *input_codec_ctx, const enum AVPixelFormat *pix_fmts) const
6814{
6815 if (params.m_hwaccel_dec_device_type == AV_HWDEVICE_TYPE_NONE)
6816 {
6817 // We should never happen to end up here...
6818 Logging::error(filename(), "Unable to decode this file using hardware acceleration: Internal error! No hardware device type set.");
6819 return AV_PIX_FMT_NONE;
6820 }
6821
6822 AVPixelFormat pix_fmt_expected = m_dec_hw_pix_fmt;
6823
6824 for (const AVPixelFormat *p = pix_fmts; *p != AV_PIX_FMT_NONE; p++)
6825 {
6826 if (*p == pix_fmt_expected)
6827 {
6828 return pix_fmt_expected;
6829 }
6830 }
6831
6832 Logging::error(filename(), "Unable to decode this file using hardware acceleration. Expected format '%1' not supported.", get_pix_fmt_name(pix_fmt_expected).c_str());
6833
6834 return AV_PIX_FMT_NONE;
6835}
6836
6837int FFmpeg_Transcoder::hwdevice_ctx_create(AVBufferRef ** hwaccel_enc_device_ctx, AVHWDeviceType dev_type, const std::string & device) const
6838{
6839 std::string active_device(device);
6840 int ret;
6841
6842 if (active_device == "AUTO" && dev_type == AV_HWDEVICE_TYPE_VAAPI)
6843 {
6844 active_device = "/dev/dri/renderD128"; //** @todo HWACCEL - Try to autodetect rendering device
6845 }
6846
6847 ret = av_hwdevice_ctx_create(hwaccel_enc_device_ctx, dev_type, !active_device.empty() ? active_device.c_str() : nullptr, nullptr, 0);
6848 if (ret < 0)
6849 {
6850 Logging::error(virtname(), "Failed to create a %1 device (error '%2').", hwdevice_get_type_name(dev_type), ffmpeg_geterror(ret).c_str());
6851 return ret;
6852 }
6853 return 0;
6854}
6855
6856int FFmpeg_Transcoder::hwdevice_ctx_add_ref(AVCodecContext *input_codec_ctx)
6857{
6858 if (m_hwaccel_dec_device_ctx == nullptr)
6859 {
6860 int ret = AVERROR(EINVAL);
6861 Logging::error(virtname(), "INTERNAL ERROR: FFmpeg_Transcoder::hwdevice_ctx_add_ref()! HW decoder device context is NULL (error '%1').", ffmpeg_geterror(ret).c_str());
6862 return ret;
6863 }
6864
6865 input_codec_ctx->hw_device_ctx = av_buffer_ref(m_hwaccel_dec_device_ctx);
6866 if (input_codec_ctx->hw_device_ctx == nullptr)
6867 {
6868 int ret = AVERROR(ENOMEM);
6869 Logging::error(virtname(), "A hardware device reference create failed (error '%1').", ffmpeg_geterror(ret).c_str());
6870 return ret;
6871 }
6872
6873 input_codec_ctx->opaque = static_cast<void*>(this);
6874 input_codec_ctx->get_format = &FFmpeg_Transcoder::get_format_static;
6875
6876 return 0;
6877}
6878
6879void FFmpeg_Transcoder::hwdevice_ctx_free(AVBufferRef **hwaccel_device_ctx)
6880{
6881 if (*hwaccel_device_ctx != nullptr)
6882 {
6883 av_buffer_unref(hwaccel_device_ctx);
6884 *hwaccel_device_ctx = nullptr;
6885 }
6886}
6887
6888int FFmpeg_Transcoder::hwframe_ctx_set(AVCodecContext *output_codec_ctx, AVCodecContext *input_codec_ctx, AVBufferRef *hw_device_ctx) const
6889{
6890 AVBufferRef *hw_new_frames_ref;
6891 AVHWFramesContext *frames_ctx = nullptr;
6892 int ret = 0;
6893
6894 hw_new_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx);
6895 if (hw_new_frames_ref == nullptr)
6896 {
6897 ret = AVERROR(ENOMEM);
6898 Logging::error(virtname(), "hwframe_ctx_set(): Failed to create hwframe context (error '%1').", ffmpeg_geterror(ret).c_str());
6899 return ret;
6900 }
6901
6902 frames_ctx = reinterpret_cast<AVHWFramesContext *>(hw_new_frames_ref->data);
6903 frames_ctx->format = m_enc_hw_pix_fmt;
6904 frames_ctx->sw_format = /*input_codec_ctx->sw_pix_fmt; */find_sw_fmt_by_hw_type(params.m_hwaccel_enc_device_type);
6905 frames_ctx->width = input_codec_ctx->width;
6906 frames_ctx->height = input_codec_ctx->height;
6907
6908 frames_ctx->initial_pool_size = 20; // Driver default seems to be 17
6909
6910 ret = av_hwframe_ctx_init(hw_new_frames_ref);
6911 if (ret < 0)
6912 {
6913 Logging::error(virtname(), "hwframe_ctx_set(): Failed to initialise hwframe context (error '%1').", ffmpeg_geterror(ret).c_str());
6914 av_buffer_unref(&hw_new_frames_ref);
6915 return ret;
6916 }
6917
6918 output_codec_ctx->hw_frames_ctx = av_buffer_ref(hw_new_frames_ref);
6919 if (output_codec_ctx->hw_frames_ctx == nullptr)
6920 {
6921 ret = AVERROR(ENOMEM);
6922 Logging::error(virtname(), "hwframe_ctx_set(): A hardware frame reference create failed (error '%1').", ffmpeg_geterror(ret).c_str());
6923 }
6924
6925 av_buffer_unref(&hw_new_frames_ref);
6926
6927 return ret;
6928}
6929
6930//int FFmpeg_Transcoder::hwframe_ctx_set(AVCodecContext *output_codec_ctx, AVCodecContext *input_codec_ctx, AVBufferRef *hw_device_ctx)
6931//{
6932// // If the decoder runs in hardware, we should use the decoder's frames context. This will save us from
6933// // having to transfer frames from hardware to software and vice versa.
6934// // If the decoder runs in software, create a new frames context.
6935// if (input_codec_ctx->hw_frames_ctx != nullptr)
6936// {
6937// Logging::debug(virtname(), "Hardware encoder init: Hardware decoder active, using decoder hw_frames_ctx for encoder.");
6938
6939// /* we need to ref hw_frames_ctx of decoder to initialize encoder's codec.
6940// Only after we get a decoded frame, can we obtain its hw_frames_ctx */
6941// output_codec_ctx->hw_frames_ctx = av_buffer_ref(input_codec_ctx->hw_frames_ctx);
6942// if (!output_codec_ctx->hw_frames_ctx)
6943// {
6944// int ret = AVERROR(ENOMEM);
6945// Logging::error(virtname(), "A hardware frame reference create failed (error '%1').", ffmpeg_geterror(ret).c_str());
6946// return ret;
6947// }
6948
6949// m_hwaccel_dec = true; /* Doing decoding in hardware */
6950// }
6951// else {
6952// Logging::debug(virtname(), "Hardware encoder init: Software decoder active, creating new hw_frames_ctx for encoder.");
6953
6954// AVBufferRef *hw_new_frames_ref;
6955// AVHWFramesContext *frames_ctx = nullptr;
6956// int ret = 0;
6957
6958// if (!(hw_new_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx)))
6959// {
6960// ret = AVERROR(ENOMEM);
6961// Logging::error(virtname(), "Failed to create hwframe context (error '%1').", ffmpeg_geterror(ret).c_str());
6962// return ret;
6963// }
6964// frames_ctx = (AVHWFramesContext *)(hw_new_frames_ref->data);
6965// frames_ctx->format = m_hw_pix_fmt;
6966// frames_ctx->sw_format = find_sw_fmt_by_hw_type(params.m_hwaccel_enc_device_type);
6967// frames_ctx->width = input_codec_ctx->width;
6968// frames_ctx->height = input_codec_ctx->height;
6969
6970// frames_ctx->initial_pool_size = 20; // Driver default: 17
6971// if ((ret = av_hwframe_ctx_init(hw_new_frames_ref)) < 0)
6972// {
6973// Logging::error(virtname(), "Failed to initialise hwframe context (error '%1').", ffmpeg_geterror(ret).c_str());
6974// av_buffer_unref(&hw_new_frames_ref);
6975// return ret;
6976// }
6977
6978// output_codec_ctx->hw_frames_ctx = av_buffer_ref(hw_new_frames_ref);
6979// if (!output_codec_ctx->hw_frames_ctx)
6980// {
6981// Logging::error(virtname(), "A hardware frame reference create failed (error '%1').", ffmpeg_geterror(AVERROR(ENOMEM)));
6982// ret = AVERROR(ENOMEM);
6983// }
6984
6985// av_buffer_unref(&hw_new_frames_ref);
6986
6987// m_hwaccel_dec = false; /* Doing decoding in software */
6988// }
6989
6990// return 0;
6991//}
6992
6993int FFmpeg_Transcoder::hwframe_copy_from_hw(AVCodecContext * /*ctx*/, FFmpeg_Frame *sw_frame, const AVFrame * hw_frame) const
6994{
6995 int ret;
6996
6997 ret = av_frame_copy_props(*sw_frame, hw_frame);
6998 if (ret < 0)
6999 {
7000 Logging::error(filename(), "Failed to copy frame properties (error '%1').", ffmpeg_geterror(ret).c_str());
7001 return ret;
7002 }
7003
7004 ret = av_hwframe_transfer_data(*sw_frame, hw_frame, 0);
7005 if (ret < 0)
7006 {
7007 Logging::error(filename(), "Error while transferring frame data from surface (error '%1').", ffmpeg_geterror(ret).c_str());
7008 return ret;
7009 }
7010
7011 return 0;
7012}
7013
7014int FFmpeg_Transcoder::hwframe_copy_to_hw(AVCodecContext *output_codec_ctx, FFmpeg_Frame *hw_frame, const AVFrame * sw_frame) const
7015{
7016 int ret;
7017
7018 ret = av_frame_copy_props(*hw_frame, sw_frame);
7019 if (ret < 0)
7020 {
7021 Logging::error(virtname(), "Failed to copy frame properties (error '%1').", ffmpeg_geterror(ret).c_str());
7022 return ret;
7023 }
7024
7025 ret = av_hwframe_get_buffer(output_codec_ctx->hw_frames_ctx, *hw_frame, 0);
7026 if (ret < 0)
7027 {
7028 Logging::error(virtname(), "Failed to copy frame buffers to hardware memory (error '%1').", ffmpeg_geterror(ret).c_str());
7029 return ret;
7030 }
7031
7032 if ((*hw_frame)->hw_frames_ctx == nullptr)
7033 {
7034 ret = AVERROR(ENOMEM);
7035 Logging::error(virtname(), "Failed to copy frame buffers to hardware memory (error '%1').", ffmpeg_geterror(ret).c_str());
7036 return ret;
7037 }
7038
7039 ret = av_hwframe_transfer_data(*hw_frame, sw_frame, 0);
7040 if (ret < 0)
7041 {
7042 Logging::error(virtname(), "Error while transferring frame data to surface (error '%1').", ffmpeg_geterror(ret).c_str());
7043 return ret;
7044 }
7045
7046 return 0;
7047}
7048
7060int FFmpeg_Transcoder::get_hw_decoder_name(AVCodecID codec_id, std::string *codec_name) const
7061{
7062 std::string codec_name_buf;
7063 int ret = 0;
7064
7065 switch (params.m_hwaccel_dec_API)
7066 {
7067 case HWACCELAPI::VAAPI:
7068 {
7069 ret = get_hw_vaapi_codec_name(codec_id, &codec_name_buf);
7070 break;
7071 }
7072 case HWACCELAPI::MMAL:
7073 {
7074 ret = get_hw_mmal_decoder_name(codec_id, &codec_name_buf);
7075 break;
7076 }
7077 //case HWACCELAPI::V4L2M2M:
7078 //{
7079 // ret = get_hw_v4l2m2m_decoder_name(codec_id, &codec_name_buf);
7080 // break;
7081 //}
7082 case HWACCELAPI::NONE:
7083 default:
7084 {
7085 ret = AVERROR_DECODER_NOT_FOUND;
7086 break;
7087 }
7088 }
7089
7090 if (codec_name != nullptr)
7091 {
7092 if (!ret)
7093 {
7094 *codec_name = codec_name_buf;
7095 }
7096 else
7097 {
7098 codec_name->clear();
7099 }
7100 }
7101
7102 return ret;
7103}
7104
7105int FFmpeg_Transcoder::get_hw_encoder_name(AVCodecID codec_id, std::string *codec_name) const
7106{
7107 std::string codec_name_buf;
7108 int ret = 0;
7109
7110 switch (params.m_hwaccel_enc_API)
7111 {
7112 case HWACCELAPI::VAAPI:
7113 {
7114 ret = get_hw_vaapi_codec_name(codec_id, &codec_name_buf);
7115 break;
7116 }
7117 case HWACCELAPI::OMX:
7118 {
7119 ret = get_hw_omx_encoder_name(codec_id, &codec_name_buf);
7120 break;
7121 }
7122 //case HWACCELAPI::V4L2M2M:
7123 //{
7124 // ret = get_hw_v4l2m2m_encoder_name(codec_id, &codec_name_buf);
7125 // break;
7126 //}
7127 case HWACCELAPI::NONE:
7128 default:
7129 {
7130 ret = AVERROR_DECODER_NOT_FOUND;
7131 break;
7132 }
7133 }
7134
7135 if (codec_name != nullptr)
7136 {
7137 if (!ret)
7138 {
7139 *codec_name = codec_name_buf;
7140 }
7141 else
7142 {
7143 codec_name->clear();
7144 }
7145 }
7146
7147 return ret;
7148}
7149
7150int FFmpeg_Transcoder::get_hw_vaapi_codec_name(AVCodecID codec_id, std::string *codec_name) const
7151{
7152 int ret = 0;
7165 switch (codec_id)
7166 {
7167 case AV_CODEC_ID_H264:
7168 {
7169 *codec_name = "h264_vaapi";
7170 break;
7171 }
7198 //case AV_CODEC_ID_MJPEG:
7199 //{
7200 // *codec_name = "mjpeg_vaapi";
7201 // break;
7202 //}
7203 case AV_CODEC_ID_MPEG2VIDEO:
7204 {
7205 *codec_name = "mpeg2_vaapi";
7206 break;
7207 }
7208 case AV_CODEC_ID_HEVC:
7209 {
7210 *codec_name = "hevc_vaapi";
7211 break;
7212 }
7213 case AV_CODEC_ID_VC1:
7214 {
7215 *codec_name = "vc1_vaapi";
7216 break;
7217 }
7218 case AV_CODEC_ID_VP8:
7219 {
7220 *codec_name = "vp9_vaapi";
7221 break;
7222 }
7223 case AV_CODEC_ID_VP9:
7224 {
7225 *codec_name = "vp9_vaapi";
7226 break;
7227 }
7228 default:
7229 {
7230 ret = AVERROR_DECODER_NOT_FOUND;
7231 break;
7232 }
7233 }
7234
7235 return ret;
7236}
7237
7238int FFmpeg_Transcoder::get_hw_mmal_decoder_name(AVCodecID codec_id, std::string *codec_name) const
7239{
7240 int ret = 0;
7250 switch (codec_id)
7251 {
7252 case AV_CODEC_ID_H264:
7253 {
7254 *codec_name = "h264_mmal";
7255 break;
7256 }
7274 case AV_CODEC_ID_MPEG2VIDEO:
7275 {
7276 *codec_name = "mpeg2_mmal";
7277 break;
7278 }
7279 case AV_CODEC_ID_MPEG4:
7280 {
7281 *codec_name = "mpeg4_mmal";
7282 break;
7283 }
7297 case AV_CODEC_ID_VC1:
7298 {
7299 *codec_name = "vc1_mmal";
7300 break;
7301 }
7302 default:
7303 {
7304 ret = AVERROR_DECODER_NOT_FOUND;
7305 break;
7306 }
7307 }
7308
7309 return ret;
7310}
7311
7312//int FFmpeg_Transcoder::get_hw_v4l2m2m_decoder_name(AVCodecID codec_id, std::string *codec_name) const
7313//{
7314// int ret = 0;
7315// /**
7316// * *** v4l2m2m (Video2linux) decoder ***
7317// *
7318// * h263_v4l2m2m V4L2 mem2mem H.263 decoder wrapper (codec h263)
7319// * h264_v4l2m2m V4L2 mem2mem H.264 decoder wrapper (codec h264)
7320// * hevc_v4l2m2m V4L2 mem2mem HEVC decoder wrapper (codec hevc)
7321// * mpeg1_v4l2m2m V4L2 mem2mem MPEG1 decoder wrapper (codec mpeg1video)
7322// * mpeg2_v4l2m2m V4L2 mem2mem MPEG2 decoder wrapper (codec mpeg2video)
7323// * mpeg4_v4l2m2m V4L2 mem2mem MPEG4 decoder wrapper (codec mpeg4)
7324// * vc1_v4l2m2m V4L2 mem2mem VC1 decoder wrapper (codec vc1)
7325// * vp8_v4l2m2m V4L2 mem2mem VP8 decoder wrapper (codec vp8)
7326// * vp9_v4l2m2m V4L2 mem2mem VP9 decoder wrapper (codec vp9)
7327// */
7328// switch (codec_id)
7329// {
7330// case AV_CODEC_ID_H263:
7331// {
7332// *codec_name = "h263_v4l2m2m";
7333// break;
7334// }
7335// case AV_CODEC_ID_H264:
7336// {
7337// *codec_name = "h264_v4l2m2m";
7338// break;
7339// }
7340// case AV_CODEC_ID_H265:
7341// {
7342// *codec_name = "hevc_v4l2m2m";
7343// break;
7344// }
7345// case AV_CODEC_ID_MPEG1VIDEO:
7346// {
7347// *codec_name = "mpeg1_v4l2m2m";
7348// break;
7349// }
7350// case AV_CODEC_ID_MPEG2VIDEO:
7351// {
7352// *codec_name = "mpeg2_v4l2m2m";
7353// break;
7354// }
7355// case AV_CODEC_ID_MPEG4:
7356// {
7357// *codec_name = "mpeg4_v4l2m2m";
7358// break;
7359// }
7360// //case AV_CODEC_ID_VC1: /** @todo WMV is currently not supported */
7361// //{
7362// // *codec_name = "vc1_v4l2m2m";
7363// // break;
7364// //}
7365// case AV_CODEC_ID_VP8:
7366// {
7367// *codec_name = "vp8_v4l2m2m";
7368// break;
7369// }
7370// case AV_CODEC_ID_VP9:
7371// {
7372// *codec_name = "vp9_v4l2m2m";
7373// break;
7374// }
7375// default:
7376// {
7377// ret = AVERROR_DECODER_NOT_FOUND;
7378// break;
7379// }
7380// }
7381
7382// return ret;
7383//}
7384
7385int FFmpeg_Transcoder::get_hw_omx_encoder_name(AVCodecID codec_id, std::string *codec_name) const
7386{
7387 int ret = 0;
7393 switch (codec_id)
7394 {
7395 case AV_CODEC_ID_H264:
7396 {
7397 *codec_name = "h264_omx";
7398 break;
7399 }
7400 default:
7401 {
7402 ret = AVERROR_DECODER_NOT_FOUND;
7403 break;
7404 }
7405 }
7406
7407 return ret;
7408}
7409
7410int FFmpeg_Transcoder::get_hw_v4l2m2m_encoder_name(AVCodecID codec_id, std::string *codec_name) const
7411{
7412 int ret = 0;
7422 switch (codec_id)
7423 {
7424 case AV_CODEC_ID_H263:
7425 {
7426 *codec_name = "h263_v4l2m2m";
7427 break;
7428 }
7429 case AV_CODEC_ID_H264:
7430 {
7431 *codec_name = "h264_v4l2m2m";
7432 break;
7433 }
7434 case AV_CODEC_ID_H265:
7435 {
7436 *codec_name = "hevc_v4l2m2m";
7437 break;
7438 }
7439 case AV_CODEC_ID_MPEG4:
7440 {
7441 *codec_name = "mpeg4_v4l2m2m";
7442 break;
7443 }
7444 case AV_CODEC_ID_VP8:
7445 {
7446 *codec_name = "vp8_v4l2m2m";
7447 break;
7448 }
7449 default:
7450 {
7451 ret = AVERROR_DECODER_NOT_FOUND;
7452 break;
7453 }
7454 }
7455
7456 return ret;
7457}
7458
7459AVPixelFormat FFmpeg_Transcoder::find_sw_fmt_by_hw_type(AVHWDeviceType type)
7460{
7461 DEVICETYPE_MAP::const_iterator it = m_devicetype_map.find(type);
7462
7463 if (it == m_devicetype_map.cend())
7464 {
7465 return AV_PIX_FMT_NONE;
7466 }
7467
7468 return it->second;
7469}
7470
7471void FFmpeg_Transcoder::get_pix_formats(AVPixelFormat *in_pix_fmt, AVPixelFormat *out_pix_fmt, AVCodecContext* output_codec_ctx) const
7472{
7473 *in_pix_fmt = static_cast<AVPixelFormat>(m_in.m_video.m_stream->codecpar->format);
7474
7476 {
7478 }
7479
7480 if (output_codec_ctx == nullptr)
7481 {
7482 output_codec_ctx = m_out.m_video.m_codec_ctx.get();
7483 }
7484
7485 // Fail safe: If output_codec_ctx is NULL, set to something common (AV_PIX_FMT_YUV420P is widely used)
7486 *out_pix_fmt = (output_codec_ctx != nullptr) ? output_codec_ctx->pix_fmt : AV_PIX_FMT_YUV420P;
7487
7488 if (*in_pix_fmt == AV_PIX_FMT_NONE)
7489 {
7490 // If input's stream pixel format is unknown, use same as output (may not work but at least will not crash FFmpeg)
7491 *in_pix_fmt = *out_pix_fmt;
7492 }
7493
7494 // If hardware acceleration is enabled, e.g., output_codec_ctx->pix_fmt is AV_PIX_FMT_VAAPI
7495 // but the format actually is AV_PIX_FMT_NV12 so we use the correct value from sw_format in
7496 // the hardware frames context.
7498 output_codec_ctx != nullptr &&
7499 output_codec_ctx->hw_frames_ctx != nullptr &&
7500 output_codec_ctx->hw_frames_ctx->data != nullptr)
7501 {
7502 *out_pix_fmt = reinterpret_cast<AVHWFramesContext*>(output_codec_ctx->hw_frames_ctx->data)->sw_format;
7503 }
7504}
7505
7506uint32_t FFmpeg_Transcoder::get_next_segment(int64_t pos) const
7507{
7508 return (static_cast<uint32_t>(pos / params.m_segment_duration + 1));
7509}
7510
7511bool FFmpeg_Transcoder::goto_next_segment(uint32_t next_segment) const
7512{
7513 return (next_segment == m_current_segment + 1 && next_segment <= m_virtualfile->get_segment_count());
7514}
7515
7516bool FFmpeg_Transcoder::is_audio_stream(int stream_idx) const
7517{
7518 return (stream_exists(stream_idx) && stream_idx == m_in.m_audio.m_stream_idx);
7519}
7520
7521bool FFmpeg_Transcoder::is_video_stream(int stream_idx) const
7522{
7523 return (stream_exists(stream_idx) && stream_idx == m_in.m_video.m_stream_idx);
7524}
7525
7527{
7528 StreamRef_map::const_iterator it = m_in.m_subtitle.find(stream_idx);
7529
7530 return (it != m_in.m_subtitle.cend());
7531}
7532
7534{
7535 StreamRef_map::iterator it = m_out.m_subtitle.find(stream_idx);
7536
7537 if (it == m_out.m_subtitle.end())
7538 {
7539 return nullptr;
7540 }
7541
7542 return &it->second;
7543}
7544
7545bool FFmpeg_Transcoder::stream_exists(int stream_idx) const
7546{
7547 return (stream_idx != INVALID_STREAM);
7548}
7549
7550void FFmpeg_Transcoder::add_stream_map(int in_stream_idx, int out_stream_idx)
7551{
7552 if (in_stream_idx != INVALID_STREAM)
7553 {
7554 m_stream_map.insert(std::make_pair(in_stream_idx, out_stream_idx));
7555 }
7556}
7557
7559{
7560 STREAM_MAP::const_iterator it = m_stream_map.find(in_stream_idx);
7561
7562 if (it == m_stream_map.cend())
7563 {
7564 return INVALID_STREAM;
7565 }
7566
7567 return (it->second);
7568}
7569
7570inline int FFmpeg_Transcoder::foreach_subtitle_file(const std::string& search_path, const std::regex& regex, int depth, const std::function<int (const std::string &, const std::optional<std::string> &)> &f)
7571{
7572 int ret = 0;
7573
7574 try
7575 {
7576 const std::filesystem::directory_iterator end;
7577 for (std::filesystem::directory_iterator iter{ search_path }; iter != end && ret == 0; iter++)
7578 {
7579 const std::string subtitle_filename(iter->path().filename().string());
7580 if (std::filesystem::is_regular_file(*iter))
7581 {
7582 if (std::regex_match(subtitle_filename, regex))
7583 {
7584 std::smatch res;
7585 if (std::regex_search(subtitle_filename.cbegin(), subtitle_filename.cend(), res, regex))
7586 {
7587 if (res[2].length())
7588 {
7589 ret = f(iter->path().string(), res[2]);
7590 }
7591 else
7592 {
7593 ret = f(iter->path().string(), std::nullopt);
7594 }
7595 }
7596 }
7597 }
7598 else if (std::filesystem::is_directory(*iter) && depth > 0)
7599 {
7600 ret = foreach_subtitle_file(iter->path().string(), regex, depth - 1, f);
7601 }
7602 }
7603 }
7604 catch (std::filesystem::filesystem_error& e)
7605 {
7606 ret = AVERROR(e.code().value());
7607 Logging::error(filename(), "Could not open directory '%1' (error '%2').", search_path.c_str(), ffmpeg_geterror(ret).c_str());
7608 }
7609 catch (std::bad_alloc & e)
7610 {
7611 ret = AVERROR(ENOMEM);
7612 Logging::error(filename(), "Could not open directory '%1' (error '%2').", search_path.c_str(), ffmpeg_geterror(ret).c_str());
7613 }
7614
7615 return ret;
7616}
7617
7618int FFmpeg_Transcoder::read_packet(void *opaque, uint8_t *buf, int buf_size)
7619{
7620 BUFFER_DATA *bd = static_cast<BUFFER_DATA *>(opaque);
7621 buf_size = FFMIN(buf_size, static_cast<int>(bd->size));
7622
7623 if (!buf_size)
7624 {
7625 return AVERROR_EOF;
7626 }
7627
7628 /* copy internal buffer data to buf */
7629 std::memcpy(buf, bd->ptr, static_cast<size_t>(buf_size));
7630 bd->ptr += buf_size;
7631 bd->size -= static_cast<size_t>(buf_size);
7632
7633 return buf_size;
7634}
7635
7636int FFmpeg_Transcoder::add_external_subtitle_stream(const std::string & subtitle_file, const std::optional<std::string> & language)
7637{
7638 AVFormatContext *format_ctx = nullptr;
7639 AVIOContext *avio_ctx = nullptr;
7640 uint8_t *buffer = nullptr;
7641 size_t buffer_size;
7642 int ret = 0;
7643
7644 if (language)
7645 {
7646 Logging::debug(filename(), "Adding external subtitle stream: %1 [%2]", subtitle_file.c_str(), language->c_str());
7647 }
7648 else
7649 {
7650 Logging::debug(filename(), "Adding external subtitle stream: %1", subtitle_file.c_str());
7651 }
7652
7653 try
7654 {
7655 uint8_t *avio_ctx_buffer = nullptr;
7656 int avio_ctx_buffer_size = 4096;
7657 BUFFER_DATA bd = { nullptr, 0 };
7658
7659 // slurp file content into buffer
7660 ret = av_file_map(subtitle_file.c_str(), &buffer, &buffer_size, 0, nullptr);
7661 if (ret < 0)
7662 {
7663 throw ret;
7664 }
7665
7666 // fill opaque structure used by the AVIOContext read callback
7667 bd.ptr = buffer;
7668 bd.size = buffer_size;
7669
7670 format_ctx = avformat_alloc_context();
7671 if (format_ctx == nullptr)
7672 {
7673 throw AVERROR(ENOMEM);
7674 }
7675
7676 avio_ctx_buffer = reinterpret_cast<uint8_t *>(av_malloc(static_cast<size_t>(avio_ctx_buffer_size)));
7677 if (avio_ctx_buffer == nullptr)
7678 {
7679 throw AVERROR(ENOMEM);
7680 }
7681
7682 avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, &bd, &read_packet, nullptr, nullptr);
7683 if (avio_ctx == nullptr)
7684 {
7685 throw AVERROR(ENOMEM);
7686 }
7687 format_ctx->pb = avio_ctx;
7688
7689 ret = avformat_open_input(&format_ctx, nullptr, nullptr, nullptr);
7690 if (ret < 0)
7691 {
7692 Logging::error(filename(), "Could not open input file (error '%1').", ffmpeg_geterror(ret).c_str());
7693 throw ret;
7694 }
7695
7696 ret = avformat_find_stream_info(format_ctx, nullptr);
7697 if (ret < 0)
7698 {
7699 Logging::error(filename(), "Could not find stream info (error '%1').", ffmpeg_geterror(ret).c_str());
7700 throw ret;
7701 }
7702
7703 //av_dump_format(format_ctx, 0, subtitle_file.c_str(), 0);
7704
7705 AVCodecContext * codec_ctx = nullptr;
7706 int stream_idx = INVALID_STREAM;
7707
7708 ret = open_bestmatch_decoder(format_ctx, &codec_ctx, &stream_idx, AVMEDIA_TYPE_SUBTITLE);
7709 if (ret < 0 && ret != AVERROR_STREAM_NOT_FOUND) // AVERROR_STREAM_NOT_FOUND is not an error
7710 {
7711 Logging::error(filename(), "Failed to open video codec (error '%1').", ffmpeg_geterror(ret).c_str());
7712 throw ret;
7713 }
7714
7715 if (ret != AVERROR_STREAM_NOT_FOUND)
7716 {
7717 AVCodecID codec_id = m_current_format->subtitle_codec(codec_ctx->codec_id); // Get matching output codec
7718
7719 if (codec_id != AV_CODEC_ID_NONE)
7720 {
7721 StreamRef input_streamref;
7722
7723 codec_ctx->pkt_timebase = codec_ctx->time_base = format_ctx->streams[0]->time_base;
7724
7725 // We have a subtitle stream
7726 input_streamref.set_codec_ctx(codec_ctx);
7727 input_streamref.m_stream = format_ctx->streams[0];
7728 input_streamref.m_stream_idx = INVALID_STREAM;
7729
7730 //m_active_stream_msk |= FFMPEGFS_SUBTITLE;
7731
7732 ret = add_subtitle_stream(codec_id, input_streamref, language);
7733 if (ret < 0)
7734 {
7735 throw ret;
7736 }
7737
7738 AVPacket pkt;
7739 int output_stream_index = ret;
7740 // Read one frame from the input file into a temporary packet.
7741 while ((ret = av_read_frame(format_ctx, &pkt)) == 0)
7742 {
7743 int decoded;
7744 ret = decode_subtitle(codec_ctx, &pkt, &decoded, output_stream_index);
7745 if (ret < 0)
7746 {
7747 throw ret;
7748 }
7749 }
7750 }
7751 }
7752
7753 if (ret == AVERROR_EOF)
7754 {
7755 ret = 0;
7756 }
7757 }
7758 catch (int _ret)
7759 {
7760 ret = _ret;
7761 }
7762
7763 avformat_close_input(&format_ctx);
7764
7765 // note: the internal buffer could have changed, and be != avio_ctx_buffer
7766 if (avio_ctx != nullptr)
7767 {
7768 av_freep(&avio_ctx->buffer);
7769 }
7770
7771 avio_context_free(&avio_ctx);
7772
7773 av_file_unmap(buffer, buffer_size);
7774
7775 return ret;
7776}
7777
7779{
7780 int ret;
7781
7782 try
7783 {
7784 std::filesystem::path file(filename());
7785 std::string stem(file.stem().string());
7786
7787 // Escape characters that are meaningful to regexp.
7788 regex_escape(&stem);
7789
7790 std::string regex_string("^(" + stem + "[.])(.*)([.]srt|[.]vtt)|^(" + stem + ")([.]srt|[.]vtt)"); // filename.srt/vtt or filename.lang.srt/vtt
7791 std::regex regex(regex_string, std::regex::ECMAScript);
7792
7793 //ret = foreach_subtitle_file(
7794 // file.parent_path(),
7795 // regex,
7796 // 0,
7797 // std::bind(&FFmpeg_Transcoder::add_external_subtitle_stream, this, std::placeholders::_1, std::placeholders::_2));
7798
7799 // clang-tidy now recommends a lambda
7801 file.parent_path().string(),
7802 regex,
7803 0,
7804 [this](const std::string & subtitle_file, const std::optional<std::string> & language)
7805 {
7806 add_external_subtitle_stream(std::forward<decltype(subtitle_file)>(subtitle_file), std::forward<decltype(language)>(language));
7807 return 0;
7808 });
7809
7810 // Ugly, but a lambda would also be possible
7811 //ret = foreach_subtitle_file(
7812 // file.parent_path(),
7813 // regex,
7814 // 0,
7815 // [this](const std::string & subtitle_file, const std::optional<std::string> & language)
7816 //{
7817 // if (language)
7818 // {
7819 // Logging::error(filename(), "[%1] %2", language->c_str(), subtitle_file.c_str());
7820 // }
7821 // else
7822 // {
7823 // Logging::error(filename(), "%1", subtitle_file.c_str());
7824 // }
7825 // return 0;
7826 //});
7827 }
7828 catch (std::regex_error & e)
7829 {
7830 ret = 0; // Ignore error
7831 Logging::error(filename(), "INTERNAL ERROR: FFmpeg_Transcoder::add_external_subtitle_streams()! Unable to create reg exp: %1", e.what());
7832 }
7833
7834 return ret;
7835}
7836
7838{
7839 MULTIFRAME_MAP::const_reverse_iterator it = m_frame_map.crbegin();
7840
7841 if (it != m_frame_map.crend())
7842 {
7843 return it->first;
7844 }
7845 else
7846 {
7847 return 0;
7848 }
7849}
7850
7852{
7853 return m_last_seek_frame_no;
7854}
AIFF file structures http://paulbourke.net/dataformats/audio/.
#define AIFF_SOUNDATAID
ckID for Sound Data Chunk
Definition: aiff.h:81
#define AIFF_COMMONID
ckID for Common Chunk
Definition: aiff.h:67
#define AIFF_FORMID
ckID for Form Chunk
Definition: aiff.h:45
Buffer class.
#define CACHE_FLAG_RW
Mark cache file writeable, implies read permissions.
Definition: buffer.h:50
@ NONE
No result code available.
The Buffer class.
Definition: buffer.h:56
virtual bool eof() const override
Check if at end of file.
Definition: buffer.cc:1048
bool segment_exists(uint32_t segment_no)
Check if segment exists.
Definition: buffer.cc:347
void finished_segment()
Complete the segment decoding.
Definition: buffer.cc:1097
virtual int seek(int64_t offset, int whence) override
Seek to position in file.
Definition: buffer.cc:771
size_t writeio(const uint8_t *data, size_t length)
Write data to the current position in the buffer. The position pointer will be updated.
Definition: buffer.cc:668
size_t write_frame(const uint8_t *data, size_t length, uint32_t frame_no)
Write image data for the frame number into the buffer.
Definition: buffer.cc:695
bool have_frame(uint32_t frame_no)
Check if we have the requested frame number. Works only when processing a frame set.
Definition: buffer.cc:1063
bool copy(std::vector< uint8_t > *out_data, size_t offset, uint32_t segment_no=0)
Copy buffered data into output buffer.
Definition: buffer.cc:882
virtual size_t tell() const override
Get the value of the internal read position pointer.
Definition: buffer.cc:828
bool set_segment(uint32_t segment_no, size_t size)
Set the current segment.
Definition: buffer.cc:303
bool open_file(uint32_t segment_no, uint32_t flags, size_t defaultsize=0)
Open the cache file if not already open.
Definition: buffer.cc:77
size_t buffer_watermark(uint32_t segment_no=0) const
Return the current watermark of the file while transcoding.
Definition: buffer.cc:869
static std::string get_sample_fmt_name(AVSampleFormat sample_fmt)
Calls av_get_sample_fmt_name and returns a std::string with the format name.
Definition: ffmpeg_base.cc:292
int get_channels(const AVCodecParameters *codecpar) const
Get the number of channels from AVCodecParameters.
Definition: ffmpeg_base.cc:331
int opt_set_with_check(void *obj, const char *key, const char *value, int flags, const char *filename=nullptr) const
Call av_opt_set and check result code. Displays an error message if appropriate.
Definition: ffmpeg_base.cc:206
int get_script_info(AVCodecContext *codec_ctx, int play_res_x, int play_res_y, const char *font, int font_size, int primary_color, int secondary_color, int outline_color, int back_color, int bold, int italic, int underline, int border_style, int alignment) const
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. Nicked from the FFmpeg API funct...
Definition: ffmpeg_base.cc:382
void audio_info(bool out_file, const AVFormatContext *format_ctx, const AVStream *stream) const
Print data from the audio stream to log.
Definition: ffmpeg_base.cc:243
int64_t frame_to_pts(AVStream *stream, uint32_t frame_no) const
Convert frame number to PTS value.
Definition: ffmpeg_base.cc:324
uint32_t pts_to_frame(AVStream *stream, int64_t pts) const
Convert PTS value to frame number.
Definition: ffmpeg_base.cc:313
void video_info(bool out_file, const AVFormatContext *format_ctx, const AVStream *stream) const
Print data from the video stream to a log.
Definition: ffmpeg_base.cc:218
void subtitle_info(bool out_file, const AVFormatContext *format_ctx, const AVStream *stream) const
Print data from the subtitle stream to log.
Definition: ffmpeg_base.cc:270
VIRTUALFILE * m_virtualfile
Underlying virtual file object.
Definition: ffmpeg_base.h:280
void video_stream_setup(AVCodecContext *output_codec_ctx, AVStream *output_stream, AVCodecContext *input_codec_ctx, AVRational framerate, AVPixelFormat enc_hw_pix_fmt) const
Set up a video stream.
Definition: ffmpeg_base.cc:68
static std::string get_channel_layout_name(const AVChannelLayout *ch_layout)
Calls av_channel_layout_describe and returns a std::string with the channel layout.
Definition: ffmpeg_base.cc:298
static std::string get_pix_fmt_name(AVPixelFormat pix_fmt)
Calls av_get_pix_fmt_name and returns a std::string with the pix format name.
Definition: ffmpeg_base.cc:286
int dict_set_with_check(AVDictionary **pm, const char *key, const char *value, int flags, const char *filename=nullptr, bool nodelete=false) const
Call av_dict_set and check the result code. It displays an error message if appropriate.
Definition: ffmpeg_base.cc:172
void set_channels(AVCodecParameters *codecpar_out, const AVCodecParameters *codecpar_in) const
Set the number of channels from AVCodecParameters.
Definition: ffmpeg_base.cc:340
The FFmpeg_Frame class.
Definition: ffmpeg_frame.h:43
int m_stream_idx
Stream index frame belongs to, or -1 (INVALID_STREAM)
Definition: ffmpeg_frame.h:121
int res() const
Get result of last operation.
static const PROFILE_LIST_VEC m_profile
List of profile options.
std::vector< PROFILE_OPTION > PROFILE_OPTION_VEC
PROFILE_OPTION array.
The FFmpeg_Subtitle class.
int m_stream_idx
Stream index frame belongs to, or -1 (INVALID_STREAM)
int res() const
Get result of last operation.
In/output stream reference data.
int m_stream_idx
Stream index in AVFormatContext.
int64_t m_start_time
Start time of the stream in stream time base units, may be 0.
AVStream * m_stream
AVStream for this encoder stream.
void reset()
Close (reset) AVCodecContext pointer.
void set_codec_ctx(AVCodecContext *codec_ctx)
Set the AVCodecContext pointer. Will be shared and deleted after the last consumer freed it.
std::shared_ptr< AVCodecContext > m_codec_ctx
AVCodecContext for this encoder stream.
The FFmpeg_Transcoder class.
int add_samples_to_fifo(uint8_t **converted_input_samples, int frame_size)
Add converted input audio samples to the FIFO buffer for later processing.
uint32_t m_current_segment
HLS only: Segment file number currently being encoded.
static bool video_size(size_t *filesize, AVCodecID codec_id, BITRATE bit_rate, int64_t duration, int width, int height, bool interleaved, const AVRational &framerate)
Predict video file size. This may (better will surely) be inaccurate.
int add_subtitle_stream(AVCodecID codec_id, StreamRef &input_streamref, const std::optional< std::string > &language=std::nullopt)
Add new subtitle stream to output file.
HWACCELMODE
Currently active hardware acceleration mode.
@ ENABLED
Hardware acceleration is active.
@ FALLBACK
Hardware acceleration selected, but fell back to software.
bool m_hwaccel_enable_enc_buffering
Enable hardware acceleration frame buffers for encoder.
int open_albumarts()
open_albumarts
static const DEVICETYPE_MAP m_devicetype_map
List of AVPixelFormats mapped to hardware acceleration types.
int open_output(Buffer *buffer)
Open output file. Data will actually be written to buffer and copied by FUSE when accessed.
int flush_frames_all(bool use_flush_packet)
Flush the remaining frames for all streams.
int stack_seek_frame(uint32_t frame_no)
Seek to a specific frame. Does not actually perform the seek, this is done asynchronously by the tran...
int get_hw_vaapi_codec_name(AVCodecID codec_id, std::string *codec_name) const
Determine VAAPI codec name.
int purge_audio_fifo()
Purge all samples in audio FIFO.
int open_bestmatch_audio()
Open the best match audio stream.
virtual const char * filename() const override
Return source filename.
int get_hw_omx_encoder_name(AVCodecID codec_id, std::string *codec_name) const
Determine OMX encoder codec name.
int process_single_fr(DECODER_STATUS *status)
AVAudioFifo * m_audio_fifo
Audio sample FIFO.
bool can_copy_stream(const AVStream *stream) const
Check if stream can be copied from input to output (AUTOCOPY option).
static int input_read(void *opaque, unsigned char *data, int size)
Custom read function for FFmpeg.
size_t purge_multiframe_map()
Purge all frames in buffer.
int get_hw_mmal_decoder_name(AVCodecID codec_id, std::string *codec_name) const
Determine MMAL decoder codec name.
bool m_hwaccel_enable_dec_buffering
Enable hardware acceleration frame buffers for decoder.
AVSampleFormat m_cur_sample_fmt
Currently selected audio sample format.
int store_packet(AVPacket *pkt, AVMediaType mediatype)
Store packet in output stream.
void purge()
Purge FIFO and map buffers and report lost packets/frames/samples.
int add_stream_copy(AVCodecID codec_id, AVMediaType codec_type)
Add new stream copy to output file.
const FFmpegfs_Format * m_current_format
Currently used output format(s)
int map_in_to_out_stream(int in_stream_idx) const
Map input stream index to output stream index.
static bool audio_size(size_t *filesize, AVCodecID codec_id, BITRATE bit_rate, int64_t duration, int channels, int sample_rate, AVSampleFormat sample_format)
Predict audio file size. This may (better will surely) be inaccurate.
bool have_seeked() const
Check if we made a seek operation.
int add_external_subtitle_streams()
Scan for external subtitle files.
int init_deinterlace_filters(AVCodecContext *codec_ctx, AVPixelFormat pix_fmt, const AVRational &avg_frame_rate, const AVRational &time_base)
Initialise video filters.
int prepare_format(AVDictionary **dict, FILETYPE filetype) const
Prepare format optimisations.
StreamRef * get_out_subtitle_stream(int stream_idx)
Get subtitle stream for the stream index.
INPUTFILE m_in
Input file information.
int decode_video_frame(AVPacket *pkt, int *decoded)
Decode one video frame.
int decode_subtitle(AVPacket *pkt, int *decoded)
Decode one subtitle.
bool m_copy_video
If true, copy video stream from source to target (just remux, no recode).
uint32_t m_inhibit_stream_msk
HLS: Currently inhibited streams bit mask. Packets temporarly go to m_hls_packet_fifo and will be pre...
std::queue< uint32_t > m_seek_to_fifo
Stack of seek requests. Will be processed FIFO.
uint32_t get_next_segment(int64_t pos) const
Calculate next HLS segment from position.
int open_subtitles()
Open all subtitles streams, if present in input file and if supported by output file....
std::queue< AVPacket * > m_hls_packet_fifo
HLS packet FIFO.
int open_bestmatch_video()
Open the best match video stream, if present in input file.
static AVPixelFormat find_sw_fmt_by_hw_type(AVHWDeviceType type)
Get the software pixel format for the given hardware acceleration.
int send_filters(FFmpeg_Frame *srcframe, int &ret)
Send video frame to the filters.
bool m_insert_keyframe
HLS only: Allow insertion of 1 keyframe.
int init_converted_samples(uint8_t ***converted_input_samples, int frame_size)
Initialise a temporary storage for the specified number of audio samples. The conversion requires tem...
static int output_write(void *opaque, const uint8_t *data, int size)
Custom write function for FFmpeg.
static bool get_output_sample_rate(int input_sample_rate, int max_sample_rate, int *output_sample_rate=nullptr)
Calculate output sample rate based on user option.
bool close_input_file()
Closes the input file if open. Can safely be called again after the file was already closed or if the...
void copy_metadata(AVDictionary **metadata_out, const AVDictionary *metadata_in, bool contentstream=true)
Process the metadata in the FFmpeg file. This should be called at the beginning, before reading audio...
int update_codec(void *opt, const PROFILE_OPTION_VEC &profile_option_vec) const
Prepare codec options.
void flush_buffers()
Flush FFmpeg's input buffers.
int add_external_subtitle_stream(const std::string &subtitle_file, const std::optional< std::string > &language)
add_external_subtitle_stream
AVFilterGraph * m_filter_graph
Video filter graph.
bool get_aspect_ratio(int width, int height, const AVRational &sar, AVRational *ar) const
Calculate aspect ratio for width/height and sample aspect ratio (sar).
enum AVPixelFormat get_format(AVCodecContext *input_codec_ctx, const enum AVPixelFormat *pix_fmts) const
uint32_t m_reset_pts
We have to reset audio/video pts to the new position.
AVBufferRef * m_hwaccel_dec_device_ctx
Hardware acceleration device context for decoder.
int init_resampler()
Initialize the audio resampler based on the input and output codec settings. If the input and output ...
Buffer * m_buffer
Pointer to cache buffer object.
int encode_video_frame(const AVFrame *frame, int *data_present)
Encode one frame worth of video to the output file.
std::shared_ptr< FileIO > m_fileio
FileIO object of input file.
bool m_skip_next_frame
After seek, skip next video frame.
void closeio()
Close transcoder, free all ressources.
int read_decode_convert_and_store(int *finished)
Read frame from source file, decode and store in FIFO.
int add_albumart_frame(AVStream *output_stream, AVPacket *pkt_in)
Add album art to stream.
int get_hw_encoder_name(AVCodecID codec_id, std::string *codec_name=nullptr) const
Get the hardware codec name as string. This is required, because e.g. the name for the software codec...
uint32_t video_frame_count() const
Get the number of video frames in file.
bool is_hls() const
Check for HLS format.
int copy_audio_to_frame_buffer(int *finished)
Copy data from audio FIFO to frame buffer. Divides WAV data into proper chunks to be fed into the enc...
int create_fake_aiff_header() const
Create a fake AIFF header Create a fake AIFF header. Inserts predicted file sizes to allow playback t...
int read_aiff_chunk(Buffer *buffer, size_t *buffoffset, const char *ID, uint8_t *chunk, size_t *size) const
Read AIFF chunk.
bool is_audio_stream(int stream_idx) const
Check for audio stream.
MULTIFRAME_MAP m_frame_map
Audio/video/subtitle frame map.
bool goto_next_segment(uint32_t next_segment) const
Check if segment number is next designated segment.
size_t predicted_filesize() const
Try to predict the recoded file size. This may (better will surely) be inaccurate.
bool is_video_stream(int stream_idx) const
Check for video stream.
static bool total_overhead(size_t *filesize, FILETYPE filetype)
Predict overhead in file size. This may (better will surely) be inaccurate.
bool is_subtitle_stream(int stream_idx) const
Check for subtitle stream.
int add_albumart_stream(const AVCodecContext *input_codec_ctx)
Add a stream for an album art.
int64_t m_pos
Generated position.
bool m_have_seeked
After seek operations this is set to make sure the trancoding result is marked RESULTCODE_INCOMPLETE ...
AVPixelFormat get_hw_pix_fmt(const AVCodec *codec, AVHWDeviceType dev_type, bool use_device_ctx) const
Determine the hardware pixel format for the codec, if applicable.
int flush_delayed_audio()
Flush delayed audio packets, if there are any.
int do_seek_frame(uint32_t frame_no)
Actually perform seek for frame. This function ensures that it is positioned at a key frame,...
int decode(AVCodecContext *codec_ctx, AVFrame *frame, int *got_frame, const AVPacket *pkt) const
const ID3v1 * id3v1tag() const
Assemble an ID3v1 file tag.
size_t calculate_predicted_filesize() const
Try to predict final file size.
int init_audio_output_frame(AVFrame *frame, int frame_size) const
Initialise one input frame for writing to the output file. The frame will be exactly frame_size sampl...
int encode_image_frame(const AVFrame *frame, int *data_present)
Encode frame to image.
static BITRATE get_prores_bitrate(int width, int height, const AVRational &framerate, bool interleaved, PRORESLEVEL profile)
Calculate the appropriate bitrate for a ProRes file given several parameters.
static int64_t seek(void *opaque, int64_t offset, int whence)
Custom seek function for FFmpeg.
uint32_t segment_count() const
Get the number of HLS segments of file.
int get_hw_v4l2m2m_encoder_name(AVCodecID codec_id, std::string *codec_name) const
Determine video for linux encoder codec name.
bool m_is_video
true if input is a video file
int alloc_picture(AVFrame *frame, AVPixelFormat pix_fmt, int width, int height) const
Allocate memory for one picture.
AVBufferRef * m_hwaccel_enc_device_ctx
Hardware acceleration device context for encoder.
static const std::vector< PRORES_BITRATE > m_prores_bitrate
ProRes bitrate table. Used for file size prediction.
int prepare_codec(void *opt, FILETYPE filetype) const
Prepare codec options for a file type.
void add_stream_map(int in_stream_idx, int out_stream_idx)
Add entry to input stream to output stream map.
int decode_frame(AVPacket *pkt)
Decode one frame.
int add_subtitle_streams()
Add all subtitle streams. Already existing streams are not added again.
int open_output_filestreams(Buffer *buffer)
Open an output file and the required encoder. Also set some basic encoder parameters....
int64_t m_cur_video_ts
If the video stream is copied and the time stamps are absent from the input stream,...
bool stream_exists(int stream_idx) const
Check if stream exists.
std::variant< FFmpeg_Frame, FFmpeg_Subtitle > MULTIFRAME
Combined audio/videoframe and subtitle.
bool is_multiformat() const
Check for an export frame format.
HWACCELMODE m_hwaccel_dec_mode
Current hardware acceleration mode for decoder.
int skip_decoded_frames(uint32_t frame_no, bool forced_seek)
Skip decoded frames or force seek to frame_no.
STREAM_MAP m_stream_map
Input stream to output stream map.
int create_audio_frame(int frame_size)
Load one audio frame from the FIFO buffer and store in frame buffer.
int write_output_file_header()
Write the header of the output file container.
int hwdevice_ctx_create(AVBufferRef **hwaccel_enc_device_ctx, AVHWDeviceType dev_type, const std::string &device) const
virtual const char * virtname() const override
Return virtual filename. Same as destination filename, but with virtual (mount) path....
void free_filters()
Free filter sinks.
virtual const char * destname() const override
Return destination filename.
uint32_t m_fake_frame_no
The MJEPG codec requires monotonically growing PTS values so we fake some to avoid them going backwar...
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
FFmpeg_Transcoder::read_packet.
int flush_frames_single(int stream_idx, bool use_flush_packet)
Flush the remaining frames.
AVFilterContext * m_buffer_sink_context
Video filter sink context.
int open_decoder(AVFormatContext *format_ctx, AVCodecContext **codec_ctx, int stream_idx, const AVCodec *input_codec, AVMediaType mediatype)
Open codec context for stream_idx.
int open_output_frame_set(Buffer *buffer)
Open output frame set. Data will actually be written to buffer and copied by FUSE when accessed.
int write_output_file_trailer()
Write the trailer of the output file container.
int create_fake_wav_header() const
Create a fake WAV header Create a fake WAV header. Inserts predicted file sizes to allow playback to ...
bool close_resample()
Close and free the resampler context.
int process_albumarts()
Copy all album arts from source to target.
int get_hw_decoder_name(AVCodecID codec_id, std::string *codec_name=nullptr) const
Get the hardware codec name as string. This is required, because e.g. the name for the software codec...
int64_t m_pts
Generated PTS.
int decode_audio_frame(AVPacket *pkt, int *decoded)
Decode one audio frame.
AVPixelFormat m_enc_hw_pix_fmt
Requested encoder hardware pixel format.
OUTPUTFILE m_out
Output file information.
int64_t m_cur_audio_ts
If the audio stream is copied and the time stamps are absent from the input stream,...
std::atomic_uint32_t m_last_seek_frame_no
If not 0, this is the last frame that we seeked to. Video sources only.
AVPixelFormat m_dec_hw_pix_fmt
Requested decoder hardware pixel format.
uint32_t last_seek_frame_no() const
Current seek frame if available.
int flush_delayed_subtitles()
Flush delayed subtitle packets, if there are any.
AVChannelLayout m_cur_ch_layout
Currently selected audio channel layout.
int process_metadata()
Copy metadata from source to target.
int init_rescaler(AVPixelFormat in_pix_fmt, int in_width, int in_height, AVPixelFormat out_pix_fmt, int out_width, int out_height)
Init image size rescaler and pixel format converter.
const char * tagcpy(char(&out)[size], const std::string &in) const
Safely copy a tag to a target buffer. If the input buffer size is larger than output the data will be...
int hwframe_copy_to_hw(AVCodecContext *output_codec_ctx, FFmpeg_Frame *hw_frame, const AVFrame *sw_frame) const
int hwframe_ctx_set(AVCodecContext *output_codec_ctx, AVCodecContext *input_codec_ctx, AVBufferRef *hw_device_ctx) const
Adds a reference to an existing decoder hardware frame context or allocates a new AVHWFramesContext t...
int open_output_file(Buffer *buffer)
Open output file. Data will actually be written to buffer and copied by FUSE when accessed.
int open_bestmatch_decoder(AVFormatContext *format_ctx, AVCodecContext **codec_ctx, int *stream_idx, AVMediaType type)
Find best match stream and open codec context for it.
time_t mtime() const
Get last modification time of file.
bool close_output_file()
Closes the output file if open and reports lost packets. Can safely be called again after the file wa...
static enum AVPixelFormat get_format_static(AVCodecContext *input_codec_ctx, const enum AVPixelFormat *pix_fmts)
std::map< AVHWDeviceType, AVPixelFormat > DEVICETYPE_MAP
Map device types to pixel formats.
int64_t duration() const
Get the file duration.
size_t purge_hls_fifo()
Purge all packets in HLS FIFO buffer.
int init_audio_fifo()
Initialise a FIFO buffer for the audio samples to be encoded.
bool is_frameset() const
Check for an export frame format.
int process_output()
Process headers of output file Write file header, process meta data and add album arts.
int start_new_segment()
HLS only: start a new HLS segment.
AVFilterContext * m_buffer_source_context
Video filter source context.
int convert_samples(uint8_t **input_data, int in_samples, uint8_t **converted_data, int *out_samples)
Convert the input audio samples into the output sample format. The conversion happens on a per-frame ...
int64_t pts() const
Get PTS (presentation time stamp) of decoded audio/video so far.
std::recursive_mutex m_seek_to_fifo_mutex
Access mutex for seek FIFO.
int flush_delayed_video()
Flush delayed video packets, if there are any.
int hwdevice_ctx_add_ref(AVCodecContext *input_codec_ctx)
Add reference to hardware device context.
int m_cur_sample_rate
Currently selected audio sample rate.
int update_format(AVDictionary **dict, const PROFILE_OPTION_VEC &option_vec) const
Update format options.
SwrContext * m_audio_resample_ctx
SwResample context for audio resampling.
bool m_copy_audio
If true, copy audio stream from source to target (just remux, no recode).
int open_input_file(LPVIRTUALFILE virtualfile, std::shared_ptr< FileIO > fio=nullptr)
void make_pts(AVPacket *pkt, int64_t *cur_ts) const
Create PTS/DTS and update the packet. If the update packet lacks time stamps, create a fictitious PTS...
int stack_seek_segment(uint32_t segment_no)
Seek to a specific HLS segment. Does not actually perform the seek, this is done asynchronously by th...
SwsContext * m_sws_ctx
Context for video filtering.
time_t m_mtime
Modified time of input file.
void produce_audio_dts(AVPacket *pkt)
Produce audio dts/pts. This is required because the target codec usually has a different frame size t...
int hwframe_copy_from_hw(AVCodecContext *output_codec_ctx, FFmpeg_Frame *sw_frame, const AVFrame *hw_frame) const
int foreach_subtitle_file(const std::string &search_path, const std::regex &regex, int depth, const std::function< int(const std::string &, const std::optional< std::string > &)> &f)
foreach_subititle_file
uint32_t m_active_stream_msk
HLS: Currently active streams bit mask. Set FFMPEGFS_AUDIO and/or FFMPEGFS_VIDEO.
static bool get_output_bit_rate(BITRATE input_bit_rate, BITRATE max_bit_rate, BITRATE *output_bit_rate=nullptr)
Calculate output bit rate based on user option.
void get_pix_formats(AVPixelFormat *in_pix_fmt, AVPixelFormat *out_pix_fmt, AVCodecContext *output_codec_ctx=nullptr) const
Get correct input and output pixel format.
int seek_frame()
Frame sets only: perform seek to a certain frame.
HWACCELMODE m_hwaccel_enc_mode
Current hardware acceleration mode for encoder.
void hwdevice_ctx_free(AVBufferRef **hwaccel_device_ctx)
Free (remove reference) to hardware device context.
bool get_video_size(int *output_width, int *output_height) const
Get the size of the output video based on user selection and apsect ratio.
int add_stream(AVCodecID codec_id)
Add new stream to output file.
int encode_subtitle(const AVSubtitle *sub, int out_stream_idx, int *data_present)
Encode one subtitle frame to the output file.
int encode_audio_frame(const AVFrame *frame, int *data_present)
Create one frame worth of audio to the output file.
const std::string & desttype() const
Get destination type.
AVCodecID subtitle_codec(AVCodecID codec_id) const
Get subtitle codec_id.
bool albumart_supported() const
Check if album arts are supported.
bool is_hls() const
Check for HLS format.
AVSampleFormat sample_format() const
Get sample format (bit width)
FILETYPE filetype() const
Get selected filetype.
bool is_frameset() const
Check for an export frame format.
bool is_multiformat() const
Check if this is some sort of multi file format (any of the following: is_frameset() or is_hls()).
AVCodecID video_codec() const
Get video codec_id.
const std::string & fileext() const
Get file extension.
const std::string & format_name() const
Convert destination type to "real" type, i.e., the file extension to be used.
AVCodecID audio_codec() const
Get audio codec_id.
Base class for I/O.
Definition: fileio.h:260
virtual int seek(int64_t offset, int whence)=0
Seek to position in file.
virtual size_t size() const =0
Get the file size.
LPVIRTUALFILE virtualfile()
Get virtual file object.
Definition: fileio.cc:113
virtual size_t readio(void *data, size_t size)=0
Read data from a file.
virtual int error() const =0
Get last error.
static std::shared_ptr< FileIO > alloc(VIRTUALTYPE type)
Allocate the correct object for type().
Definition: fileio.cc:63
virtual bool eof() const =0
Check if at end of file.
static void warning(const T filename, const std::string &format_string, Args &&...args)
Write warning level log entry.
Definition: logging.h:220
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
Definition: logging.h:182
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
Definition: logging.h:163
static void info(const T filename, const std::string &format_string, Args &&...args)
Write info level log entry.
Definition: logging.h:201
static void error(const T filename, const std::string &format_string, Args &&...args)
Write error level log entry.
Definition: logging.h:239
#define ASS_DEFAULT_PLAYRESY
Default Y resolution.
Definition: ffmpeg_base.h:217
#define ASS_DEFAULT_ALIGNMENT
Default alignment: bottom centre Alignment values are based on the numeric keypad....
Definition: ffmpeg_base.h:250
#define ASS_DEFAULT_PLAYRESX
Default X resolution.
Definition: ffmpeg_base.h:216
#define ASS_DEFAULT_COLOUR
Default foreground colour: white.
Definition: ffmpeg_base.h:230
#define ASS_DEFAULT_BACK_COLOUR
Default background colour.
Definition: ffmpeg_base.h:231
#define ASS_DEFAULT_FONT_SIZE
Default font size.
Definition: ffmpeg_base.h:219
#define ASS_DEFAULT_BORDERSTYLE
Default border style: outline with shadow 1 - Outline with shadow, 3 - Rendered with an opaque box.
Definition: ffmpeg_base.h:256
#define ASS_DEFAULT_FONT
Default font name.
Definition: ffmpeg_base.h:218
#define ASS_DEFAULT_BOLD
Default no bold font.
Definition: ffmpeg_base.h:232
#define ASS_DEFAULT_UNDERLINE
Default no underline.
Definition: ffmpeg_base.h:234
#define ASS_DEFAULT_ITALIC
Default no italics.
Definition: ffmpeg_base.h:233
#define LAVU_DEP_OLD_CHANNEL_LAYOUT
#define OPT_VIDEO
For videos (not audio only)
#define OPT_HW_ONLY
Use this option for hardware encoding only.
#define OPT_AUDIO
For audio only files.
#define OPT_SW_ONLY
Use this option for software encoding only.
#define FRAME_SEEK_THRESHOLD
Ignore seek if target is within the next n frames.
FFmpeg transcoder.
#define MAX_PRORES_FRAMERATE
Number of selectable fram rates.
#define FFMPEGFS_AUDIO
Denote an audio stream.
#define FFMPEGFS_VIDEO
Denote a video stream.
DECODER_STATUS
Decoder status codes. Can be error, success or end of file.
@ DEC_ERROR
Decoder error, see return code.
@ DEC_EOF
Read to end of file.
@ DEC_SUCCESS
Frame decoded successfully.
const char * get_codec_name(AVCodecID codec_id, bool long_name)
Safe way to get the codec name. Function never fails, will return "unknown" on error.
std::string format_duration(int64_t value, uint32_t fracs)
Format a time in format HH:MM:SS.fract.
int strcasecmp(const std::string &s1, const std::string &s2)
strcasecmp() equivalent for std::string.
bool is_album_art(AVCodecID codec_id, const AVRational *frame_rate)
Minimal check if codec is an album art. Requires frame_rate to decide whether this is a video stream ...
const char * get_media_type_string(enum AVMediaType media_type)
av_get_media_type_string is missing, so we provide our own.
const std::string & regex_escape(std::string *str)
Escape characters that are meaningful to regexp.
const char * hwdevice_get_type_name(AVHWDeviceType dev_type)
int64_t ffmpeg_rescale_q_rnd(int64_t ts, const AVRational &timebase_in, const AVRational &timebase_out)
Convert a FFmpeg time from in timebase to out timebase with rounding.
std::string format_samplerate(int value)
Format a samplerate.
std::string make_filename(uint32_t file_no, const std::string &fileext)
Make a file name from file number and file extension.
std::string format_bitrate(BITRATE value)
Format a bit rate.
int print_stream_info(const AVStream *stream)
Print info about an AVStream.
void stat_set_size(struct stat *st, size_t size)
Properly fill in all size related members in stat struct.
void init_id3v1(ID3v1 *id3v1)
Initialise ID3v1 tag.
FILETYPE get_filetype_from_list(const std::string &desttypelist)
Get the FFmpegfs filetype, desttypelist must be a comma separated list of FFmpeg's "official" short n...
int64_t ffmpeg_rescale_q(int64_t ts, const AVRational &timebase_in, const AVRational &timebase_out)
Convert a FFmpeg time from in timebase to outtime base.
std::string ffmpeg_geterror(int errnum)
Get FFmpeg error string for errnum. Internally calls av_strerror().
PRORESLEVEL
Definition: ffmpeg_utils.h:210
#define BITRATE
For FFmpeg bit rate is an int.
Definition: ffmpeg_utils.h:145
#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE
AV_CODEC_CAP_VARIABLE_FRAME_SIZE is missing in older FFmpeg versions.
Definition: ffmpeg_utils.h:139
#define FF_INPUT_BUFFER_PADDING_SIZE
FF_INPUT_BUFFER_PADDING_SIZE is missing in newer FFmpeg versions.
Definition: ffmpeg_utils.h:135
#define AV_CODEC_FLAG_GLOBAL_HEADER
AV_CODEC_FLAG_GLOBAL_HEADER is missing in older FFmpeg versions.
Definition: ffmpeg_utils.h:131
@ STRICT
Copy stream if codec matches desired target, transcode otherwise.
@ MATCH
Copy stream if target supports codec.
@ MATCHLIMIT
Same as MATCH, only copy if target not larger transcode otherwise.
@ OFF
Never copy streams, transcode always.
@ STRICTLIMIT
Same as STRICT, only copy if target not larger, transcode otherwise.
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
Definition: ffmpeg_utils.h:737
FILETYPE
Definition: ffmpeg_utils.h:154
#define INVALID_STREAM
Denote an invalid stream.
Definition: ffmpeg_utils.h:77
#define SAFE_VALUE(p, v, d)
Access struct/class pointer safely, return default if nullptr.
Definition: ffmpeg_utils.h:148
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
Definition: ffmpegfs.cc:74
bool check_hwaccel_dec_blocked(AVCodecID codec_id, int profile)
Check if codec_id and the optional profile are in the block list.
Definition: ffmpegfs.cc:1585
std::string get_hwaccel_API_text(HWACCELAPI hwaccel_API)
Get the selected hardware acceleration as text.
Definition: ffmpegfs.cc:1603
Main include for FFmpegfs project.
LPVIRTUALFILE find_file(const std::string &virtfile)
Find file in cache.
Definition: fuseops.cc:1734
@ DVD
DVD file.
@ BLURAY
Blu-ray disk file.
@ VCD
Video CD file.
#define VIRTUALFLAG_CUESHEET
File is part of a set of cue sheet tracks or the directory.
Definition: fileio.h:117
#define VIRTUALFLAG_HIDDEN
File is not transcodable or should otherwise show in listings.
Definition: fileio.h:118
#define ID3V1_TAG_LENGTH
Fixed 128 bytes.
Definition: id3v1tag.h:58
Provide various log facilities to stderr, disk or syslog.
uint32_t m_ckSize
Size of this chunk - 8.
Definition: aiff.h:63
AIFF_ID m_ckID
Chunk ID.
Definition: aiff.h:62
uint32_t m_ckSize
Total file size - 8.
Definition: aiff.h:52
uint32_t m_ckSize
Total size of sound data chunk - 8.
Definition: aiff.h:88
std::string m_hwaccel_enc_device
Encoder device. May be AUTO to auto detect or empty.
Definition: ffmpegfs.h:222
AVHWDeviceType m_hwaccel_dec_device_type
Enable hardware acceleration buffering for decoder.
Definition: ffmpegfs.h:224
int m_deinterlace
1: deinterlace video, 0: no deinterlace
Definition: ffmpegfs.h:215
int m_decoding_errors
Break transcoding on decoding error.
Definition: ffmpegfs.h:256
AVHWDeviceType m_hwaccel_enc_device_type
Enable hardware acceleration buffering for encoder.
Definition: ffmpegfs.h:221
int m_no_subtitles
0: allow subtitles, 1: do no transcode subtitles
Definition: ffmpegfs.h:228
std::string m_hwaccel_dec_device
Decoder device. May be AUTO to auto detect or empty.
Definition: ffmpegfs.h:225
const FFmpegfs_Format * current_format(LPCVIRTUALFILE virtualfile) const
Get FFmpegfs_Format for a virtual file.
Definition: ffmpegfs.cc:235
int m_audiochannels
Max. number of audio channels.
Definition: ffmpegfs.h:209
int64_t m_min_seek_time_diff
Minimum time diff from current to next requested segment to perform a seek, in AV_TIME_BASE fractiona...
Definition: ffmpegfs.h:218
int m_videowidth
Output video width.
Definition: ffmpegfs.h:213
BITRATE m_videobitrate
Output video bit rate (bits per second)
Definition: ffmpegfs.h:212
HWACCELAPI m_hwaccel_dec_API
Decoder API.
Definition: ffmpegfs.h:223
int m_videoheight
Output video height.
Definition: ffmpegfs.h:214
int64_t m_segment_duration
Duration of one HLS segment file, in AV_TIME_BASE fractional seconds.
Definition: ffmpegfs.h:217
BITRATE m_audiobitrate
Output audio bit rate (bits per second)
Definition: ffmpegfs.h:207
PROFILE m_profile
Target profile: Firefox, MS Edge/IE or other.
Definition: ffmpegfs.h:204
int m_audiosamplerate
Output audio sample rate (in Hz)
Definition: ffmpegfs.h:208
PRORESLEVEL m_level
Level, currently proxy/hq/lt/HQ (ProRes only)
Definition: ffmpegfs.h:205
int m_noalbumarts
Skip album arts.
Definition: ffmpegfs.h:230
HWACCELAPI m_hwaccel_enc_API
Encoder API.
Definition: ffmpegfs.h:220
AUTOCOPY m_autocopy
Copy streams if codec matches.
Definition: ffmpegfs.h:202
Buffer structure, used in FFmpeg_Transcoder::read_packet.
size_t size
Size left in the buffer.
uint8_t * ptr
Pointer to buffer.
AVFormatContext * m_format_ctx
Output format context.
StreamRef_map m_subtitle
Subtitle stream information.
AVPixelFormat m_pix_fmt
Video stream pixel format.
std::vector< StreamRef > m_album_art
Album art stream.
StreamRef m_audio
Audio stream information.
StreamRef m_video
Video stream information.
FILETYPE m_filetype
File type, MP3, MP4, OPUS etc.
int64_t m_video_pts
Global timestamp for the video frames in output video stream time base units
ID3v1 m_id3v1
mp3 only, can be referenced at any time
int64_t m_audio_pts
Global timestamp for the audio frames in output audio stream time base units
int64_t m_last_mux_dts
Last muxed DTS.
ID3 version 1 tag
Definition: id3v1tag.h:42
std::array< char, 30 > m_title
Title of sound track.
Definition: id3v1tag.h:44
std::array< char, 30 > m_artist
Artist name.
Definition: id3v1tag.h:45
std::array< char, 30 > m_album
Album name.
Definition: id3v1tag.h:46
char m_title_no
Title number.
Definition: id3v1tag.h:50
std::array< char, 4 > m_year
Year of publishing.
Definition: id3v1tag.h:47
std::array< char, 28 > m_comment
Any user comments.
Definition: id3v1tag.h:48
std::string m_artist
Track artist.
Definition: fileio.h:232
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Definition: fileio.h:239
std::string m_album
Album title.
Definition: fileio.h:234
std::string m_title
Track title.
Definition: fileio.h:233
int64_t m_start
Track start time, in AV_TIME_BASE fractional seconds.
Definition: fileio.h:238
int m_trackno
Track number.
Definition: fileio.h:231
int m_tracktotal
Total number of tracks in cue sheet.
Definition: fileio.h:230
std::string m_genre
Album genre.
Definition: fileio.h:235
std::string m_date
Publishing date.
Definition: fileio.h:236
Virtual file definition.
Definition: fileio.h:123
std::string m_destfile
Name and path of destination file.
Definition: fileio.h:150
size_t m_predicted_size
Use this as the size instead of computing it over and over.
Definition: fileio.h:157
VIRTUALTYPE m_type
Type of this virtual file.
Definition: fileio.h:146
std::string m_origfile
Sanitised name and path of original file.
Definition: fileio.h:152
int m_flags
One of the VIRTUALFLAG_* flags.
Definition: fileio.h:147
int m_width
Video width - Filled in for the DVD/Blu-ray directory.
Definition: fileio.h:249
int m_height
Video height - Filled in for the DVD/Blu-ray directory.
Definition: fileio.h:250
std::string m_virtfile
Name and path of virtual file.
Definition: fileio.h:151
AVRational m_framerate
Video frame rate - Filled in for the DVD/Blu-ray directory.
Definition: fileio.h:251
struct stat m_st
stat structure with size etc.
Definition: fileio.h:153
struct VIRTUALFILE::CUESHEET_TRACK m_cuesheet_track
Cue sheet data for track.
uint32_t get_segment_count() const
Number of HLS segments in set.
Definition: fileio.cc:45
uint32_t m_video_frame_count
Number of frames in video or 0 if not a video.
Definition: fileio.h:158
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Definition: fileio.h:156
WAVE data header structure.
Definition: wave.h:129
uint32_t m_data_bytes
Number of bytes in data. Number of samples * num_channels * bit_depth / 8.
Definition: wave.h:131
WAVE "fact" header structure.
Definition: wave.h:102
std::array< uint8_t, 4 > m_chunk_id
Chunk ID 4 0x66 0x61 0x63 0x74 (i.e. "fact")
Definition: wave.h:103
WAVE header structure.
Definition: wave.h:50
uint32_t m_wav_size
Definition: wave.h:63
uint16_t m_audio_format
Should be 1 for PCM. 3 for IEEE Float.
Definition: wave.h:70
WAVE list header structure.
Definition: wave.h:116
uint32_t m_data_bytes
Number of bytes in list.
Definition: wave.h:118
Delete helper struct for std::shared_ptr<AVCodecContext>
WAVE file structures https://wavefilegem.com/how_wave_files_work.html.
struct WAV_LIST_HEADER WAV_LIST_HEADER
WAVE list header structure.
struct WAV_HEADER WAV_HEADER
WAVE header structure.
struct WAV_DATA_HEADER WAV_DATA_HEADER
WAVE data header structure.
struct WAV_FACT WAV_FACT
WAVE "fact" header structure.
struct WAV_HEADER_EX WAV_HEADER_EX
WAVE extended header structure.