OpenShot Library | libopenshot 1.1.1
FFmpegReader.cpp
Go to the documentation of this file.
1
12// Copyright (c) 2008-2024 OpenShot Studios, LLC, Fabrice Bellard
13//
14// SPDX-License-Identifier: LGPL-3.0-or-later
15
16#include <thread> // for std::this_thread::sleep_for
17#include <chrono> // for std::chrono::milliseconds
18#include <algorithm>
19#include <cmath>
20#include <sstream>
21#include <unistd.h>
22
23#include <QTransform>
24
25#include "FFmpegUtilities.h"
26#include "FFmpegColorRange.h"
27#include "PreviewSize.h"
28#include "effects/CropHelpers.h"
29
30#include "FFmpegReader.h"
31#include "Exceptions.h"
32#include "MemoryTrim.h"
33#include "Timeline.h"
34#include "Logger.h"
35
36#define ENABLE_VAAPI 0
37
38#if USE_HW_ACCEL
39#define MAX_SUPPORTED_WIDTH 1950
40#define MAX_SUPPORTED_HEIGHT 1100
41
42#if ENABLE_VAAPI
43#include "libavutil/hwcontext_vaapi.h"
44
45typedef struct VAAPIDecodeContext {
46 VAProfile va_profile;
47 VAEntrypoint va_entrypoint;
48 VAConfigID va_config;
49 VAContextID va_context;
50
51#if FF_API_STRUCT_VAAPI_CONTEXT
52 // FF_DISABLE_DEPRECATION_WARNINGS
53 int have_old_context;
54 struct vaapi_context *old_context;
55 AVBufferRef *device_ref;
56 // FF_ENABLE_DEPRECATION_WARNINGS
57#endif
58
59 AVHWDeviceContext *device;
60 AVVAAPIDeviceContext *hwctx;
61
62 AVHWFramesContext *frames;
63 AVVAAPIFramesContext *hwfc;
64
65 enum AVPixelFormat surface_format;
66 int surface_count;
67 } VAAPIDecodeContext;
68#endif // ENABLE_VAAPI
69#endif // USE_HW_ACCEL
70
71
72using namespace openshot;
73
74int hw_de_on = 0;
75#if USE_HW_ACCEL
76 AVPixelFormat hw_de_av_pix_fmt_global = AV_PIX_FMT_NONE;
77 AVHWDeviceType hw_de_av_device_type_global = AV_HWDEVICE_TYPE_NONE;
78#endif
79
80
81FFmpegReader::FFmpegReader(const std::string &path, bool inspect_reader)
82 : FFmpegReader(path, DurationStrategy::VideoPreferred, inspect_reader) {}
83
84FFmpegReader::FFmpegReader(const std::string &path, DurationStrategy duration_strategy, bool inspect_reader)
85 : path(path), pFormatCtx(NULL), videoStream(-1), audioStream(-1), pCodecCtx(NULL), aCodecCtx(NULL),
86 pStream(NULL), aStream(NULL), packet(NULL), pFrame(NULL), is_open(false), is_duration_known(false),
87 check_interlace(false), check_fps(false), duration_strategy(duration_strategy), previous_packet_location{-1, 0},
88 is_seeking(false), seeking_pts(0), seeking_frame(0), is_video_seek(true), seek_count(0),
89 seek_audio_frame_found(0), seek_video_frame_found(0), last_seek_max_frame(-1), seek_stagnant_count(0),
90 last_frame(0), largest_frame_processed(0), current_video_frame(0), audio_pts(0), video_pts(0),
91 hold_packet(false), pts_offset_seconds(0.0), audio_pts_seconds(0.0), video_pts_seconds(0.0),
92 NO_PTS_OFFSET(-99999), source_width(0), source_height(0), source_rotation(0.0), enable_seek(true) {
93
94 // Initialize FFMpeg, and register all formats and codecs
97
98 // Init timestamp offsets
99 pts_offset_seconds = NO_PTS_OFFSET;
100 video_pts_seconds = NO_PTS_OFFSET;
101 audio_pts_seconds = NO_PTS_OFFSET;
102
103 // Init cache
104 const int init_working_cache_frames = std::max(Settings::Instance()->CACHE_MIN_FRAMES, OPEN_MP_NUM_PROCESSORS * 4);
105 const int init_final_cache_frames = std::max(Settings::Instance()->CACHE_MIN_FRAMES, OPEN_MP_NUM_PROCESSORS * 4);
106 working_cache.SetMaxBytesFromInfo(init_working_cache_frames, info.width, info.height, info.sample_rate, info.channels);
108
109 // Open and Close the reader, to populate its attributes (such as height, width, etc...)
110 if (inspect_reader) {
111 Open();
112 Close();
113 }
114}
115
117 if (is_open)
118 // Auto close reader if not already done
119 Close();
120}
121
122// This struct holds the associated video frame and starting sample # for an audio packet.
123bool AudioLocation::is_near(AudioLocation location, int samples_per_frame, int64_t amount) {
124 // Is frame even close to this one?
125 if (abs(location.frame - frame) >= 2)
126 // This is too far away to be considered
127 return false;
128
129 // Note that samples_per_frame can vary slightly frame to frame when the
130 // audio sampling rate is not an integer multiple of the video fps.
131 int64_t diff = samples_per_frame * (location.frame - frame) + location.sample_start - sample_start;
132 if (abs(diff) <= amount)
133 // close
134 return true;
135
136 // not close
137 return false;
138}
139
140#if USE_HW_ACCEL
141
142// Get hardware pix format
143static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts)
144{
145 const enum AVPixelFormat *p;
146
147 // Prefer only the format matching the selected hardware decoder
149
150 for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
151 switch (*p) {
152#if defined(__linux__)
153 // Linux pix formats
154 case AV_PIX_FMT_VAAPI:
155 if (selected == 1) {
156 hw_de_av_pix_fmt_global = AV_PIX_FMT_VAAPI;
157 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VAAPI;
158 return *p;
159 }
160 break;
161 case AV_PIX_FMT_VDPAU:
162 if (selected == 6) {
163 hw_de_av_pix_fmt_global = AV_PIX_FMT_VDPAU;
164 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VDPAU;
165 return *p;
166 }
167 break;
168#endif
169#if defined(_WIN32)
170 // Windows pix formats
171 case AV_PIX_FMT_DXVA2_VLD:
172 if (selected == 3) {
173 hw_de_av_pix_fmt_global = AV_PIX_FMT_DXVA2_VLD;
174 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_DXVA2;
175 return *p;
176 }
177 break;
178 case AV_PIX_FMT_D3D11:
179 if (selected == 4) {
180 hw_de_av_pix_fmt_global = AV_PIX_FMT_D3D11;
181 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_D3D11VA;
182 return *p;
183 }
184 break;
185#endif
186#if defined(__APPLE__)
187 // Apple pix formats
188 case AV_PIX_FMT_VIDEOTOOLBOX:
189 if (selected == 5) {
190 hw_de_av_pix_fmt_global = AV_PIX_FMT_VIDEOTOOLBOX;
191 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
192 return *p;
193 }
194 break;
195#endif
196 // Cross-platform pix formats
197 case AV_PIX_FMT_CUDA:
198 if (selected == 2) {
199 hw_de_av_pix_fmt_global = AV_PIX_FMT_CUDA;
200 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_CUDA;
201 return *p;
202 }
203 break;
204 case AV_PIX_FMT_QSV:
205 if (selected == 7) {
206 hw_de_av_pix_fmt_global = AV_PIX_FMT_QSV;
207 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_QSV;
208 return *p;
209 }
210 break;
211 default:
212 // This is only here to silence unused-enum warnings
213 break;
214 }
215 }
216 Logger::Instance()->AppendDebugMethod("FFmpegReader::get_hw_dec_format (Unable to decode this file using hardware decode)");
217 return AV_PIX_FMT_NONE;
218}
219
220int FFmpegReader::IsHardwareDecodeSupported(int codecid)
221{
222 int ret;
223 switch (codecid) {
224 case AV_CODEC_ID_H264:
225 case AV_CODEC_ID_MPEG2VIDEO:
226 case AV_CODEC_ID_VC1:
227 case AV_CODEC_ID_WMV1:
228 case AV_CODEC_ID_WMV2:
229 case AV_CODEC_ID_WMV3:
230 ret = 1;
231 break;
232 default :
233 ret = 0;
234 break;
235 }
236 return ret;
237}
238#endif // USE_HW_ACCEL
239
241 // Check lifecycle state only after any in-flight Open/Close has finished.
242 const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
243 // Open reader if not already open
244 if (!is_open) {
245
246 // Initialize format context
247 pFormatCtx = NULL;
248 {
249 hw_de_on = (!force_sw_decode && openshot::Settings::Instance()->HARDWARE_DECODER != 0 ? 1 : 0);
250 hw_decode_failed = false;
251 hw_decode_error_count = 0;
252 hw_decode_succeeded = false;
253 Logger::Instance()->AppendDebugMethod("Decode hardware acceleration settings", "hw_de_on", hw_de_on, "HARDWARE_DECODER", openshot::Settings::Instance()->HARDWARE_DECODER);
254 }
255
256 // Open video file
257 if (avformat_open_input(&pFormatCtx, path.c_str(), NULL, NULL) != 0)
258 throw InvalidFile("FFmpegReader could not open media file.", path);
259
260 // Retrieve stream information
261 if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
262 throw NoStreamsFound("No streams found in file.", path);
263
264 videoStream = -1;
265 audioStream = -1;
266
267 // Init end-of-file detection variables
268 packet_status.reset(true);
269
270 // Loop through each stream, and identify the video and audio stream index
271 for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
272 // Is this a video stream?
273 if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
274 videoStream = i;
275 packet_status.video_eof = false;
276 packet_status.packets_eof = false;
277 packet_status.end_of_file = false;
278 }
279 // Is this an audio stream?
280 if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
281 audioStream = i;
282 packet_status.audio_eof = false;
283 packet_status.packets_eof = false;
284 packet_status.end_of_file = false;
285 }
286 }
287 if (videoStream == -1 && audioStream == -1)
288 throw NoStreamsFound("No video or audio streams found in this file.", path);
289
290 // Is there a video stream?
291 if (videoStream != -1) {
292 // Set the stream index
293 info.video_stream_index = videoStream;
294
295 // Set the codec and codec context pointers
296 pStream = pFormatCtx->streams[videoStream];
297
298 // Find the codec ID from stream
299 const AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(pStream);
300
301 // Get codec and codec context from stream
302 const AVCodec *pCodec = avcodec_find_decoder(codecId);
303 AVDictionary *opts = NULL;
304 int retry_decode_open = 2;
305 // If hw accel is selected but hardware cannot handle repeat with software decoding
306 do {
307 pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec);
308#if USE_HW_ACCEL
309 if (hw_de_on && (retry_decode_open==2)) {
310 // Up to here no decision is made if hardware or software decode
311 hw_de_supported = IsHardwareDecodeSupported(pCodecCtx->codec_id);
312 }
313#endif
314 retry_decode_open = 0;
315
316 // Set number of threads equal to number of processors (not to exceed 16)
317 pCodecCtx->thread_count = std::min(FF_VIDEO_NUM_PROCESSORS, 16);
318
319 if (pCodec == NULL) {
320 throw InvalidCodec("A valid video codec could not be found for this file.", path);
321 }
322
323 // Init options
324 av_dict_set(&opts, "strict", "experimental", 0);
325#if USE_HW_ACCEL
326 if (hw_de_on && hw_de_supported) {
327 // Open Hardware Acceleration
328 int i_decoder_hw = 0;
329 char adapter[256];
330 char *adapter_ptr = NULL;
331 int adapter_num;
333 Logger::Instance()->AppendDebugMethod("Hardware decoding device number", "adapter_num", adapter_num);
334
335 // Set hardware pix format (callback)
336 pCodecCtx->get_format = get_hw_dec_format;
337
338 if (adapter_num < 3 && adapter_num >=0) {
339#if defined(__linux__)
340 snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128);
341 adapter_ptr = adapter;
343 switch (i_decoder_hw) {
344 case 1:
345 hw_de_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
346 break;
347 case 2:
348 hw_de_av_device_type = AV_HWDEVICE_TYPE_CUDA;
349 break;
350 case 6:
351 hw_de_av_device_type = AV_HWDEVICE_TYPE_VDPAU;
352 break;
353 case 7:
354 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
355 break;
356 default:
357 hw_de_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
358 break;
359 }
360
361#elif defined(_WIN32)
362 adapter_ptr = NULL;
364 switch (i_decoder_hw) {
365 case 2:
366 hw_de_av_device_type = AV_HWDEVICE_TYPE_CUDA;
367 break;
368 case 3:
369 hw_de_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
370 break;
371 case 4:
372 hw_de_av_device_type = AV_HWDEVICE_TYPE_D3D11VA;
373 break;
374 case 7:
375 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
376 break;
377 default:
378 hw_de_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
379 break;
380 }
381#elif defined(__APPLE__)
382 adapter_ptr = NULL;
384 switch (i_decoder_hw) {
385 case 5:
386 hw_de_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
387 break;
388 case 7:
389 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
390 break;
391 default:
392 hw_de_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
393 break;
394 }
395#endif
396
397 } else {
398 adapter_ptr = NULL; // Just to be sure
399 }
400
401 // Check if it is there and writable
402#if defined(__linux__)
403 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
404#elif defined(_WIN32)
405 if( adapter_ptr != NULL ) {
406#elif defined(__APPLE__)
407 if( adapter_ptr != NULL ) {
408#endif
409 Logger::Instance()->AppendDebugMethod("Decode Device present using device");
410 }
411 else {
412 adapter_ptr = NULL; // use default
413 Logger::Instance()->AppendDebugMethod("Decode Device not present using default");
414 }
415
416 hw_device_ctx = NULL;
417 // Here the first hardware initialisations are made
418 if (av_hwdevice_ctx_create(&hw_device_ctx, hw_de_av_device_type, adapter_ptr, NULL, 0) >= 0) {
419 const char* hw_name = av_hwdevice_get_type_name(hw_de_av_device_type);
420 std::string hw_msg = "HW decode active: ";
421 hw_msg += (hw_name ? hw_name : "unknown");
422 Logger::Instance()->Log(hw_msg);
423 if (!(pCodecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx))) {
424 throw InvalidCodec("Hardware device reference create failed.", path);
425 }
426
427 /*
428 av_buffer_unref(&ist->hw_frames_ctx);
429 ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
430 if (!ist->hw_frames_ctx) {
431 av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA frames context\n");
432 return AVERROR(ENOMEM);
433 }
434
435 frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data;
436
437 frames_ctx->format = AV_PIX_FMT_CUDA;
438 frames_ctx->sw_format = avctx->sw_pix_fmt;
439 frames_ctx->width = avctx->width;
440 frames_ctx->height = avctx->height;
441
442 av_log(avctx, AV_LOG_DEBUG, "Initializing CUDA frames context: sw_format = %s, width = %d, height = %d\n",
443 av_get_pix_fmt_name(frames_ctx->sw_format), frames_ctx->width, frames_ctx->height);
444
445
446 ret = av_hwframe_ctx_init(pCodecCtx->hw_device_ctx);
447 ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
448 if (ret < 0) {
449 av_log(avctx, AV_LOG_ERROR, "Error initializing a CUDA frame pool\n");
450 return ret;
451 }
452 */
453 }
454 else {
455 Logger::Instance()->Log("HW decode active: no (falling back to software)");
456 throw InvalidCodec("Hardware device create failed.", path);
457 }
458 }
459#endif // USE_HW_ACCEL
460
461 // Disable per-frame threading for album arts
462 // Using FF_THREAD_FRAME adds one frame decoding delay per thread,
463 // but there's only one frame in this case.
464 if (HasAlbumArt())
465 {
466 pCodecCtx->thread_type &= ~FF_THREAD_FRAME;
467 }
468
469 // Open video codec
470 int avcodec_return = avcodec_open2(pCodecCtx, pCodec, &opts);
471 if (avcodec_return < 0) {
472 std::stringstream avcodec_error_msg;
473 avcodec_error_msg << "A video codec was found, but could not be opened. Error: " << av_err2string(avcodec_return);
474 throw InvalidCodec(avcodec_error_msg.str(), path);
475 }
476
477#if USE_HW_ACCEL
478 if (hw_de_on && hw_de_supported) {
479 AVHWFramesConstraints *constraints = NULL;
480 void *hwconfig = NULL;
481 hwconfig = av_hwdevice_hwconfig_alloc(hw_device_ctx);
482
483// TODO: needs va_config!
484#if ENABLE_VAAPI
485 ((AVVAAPIHWConfig *)hwconfig)->config_id = ((VAAPIDecodeContext *)(pCodecCtx->priv_data))->va_config;
486 constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx,hwconfig);
487#endif // ENABLE_VAAPI
488 if (constraints) {
489 if (pCodecCtx->coded_width < constraints->min_width ||
490 pCodecCtx->coded_height < constraints->min_height ||
491 pCodecCtx->coded_width > constraints->max_width ||
492 pCodecCtx->coded_height > constraints->max_height) {
493 Logger::Instance()->AppendDebugMethod("DIMENSIONS ARE TOO LARGE for hardware acceleration\n");
494 hw_de_supported = 0;
495 retry_decode_open = 1;
496 AV_FREE_CONTEXT(pCodecCtx);
497 if (hw_device_ctx) {
498 av_buffer_unref(&hw_device_ctx);
499 hw_device_ctx = NULL;
500 }
501 }
502 else {
503 // All is just peachy
504 Logger::Instance()->AppendDebugMethod("\nDecode hardware acceleration is used\n", "Min width :", constraints->min_width, "Min Height :", constraints->min_height, "MaxWidth :", constraints->max_width, "MaxHeight :", constraints->max_height, "Frame width :", pCodecCtx->coded_width, "Frame height :", pCodecCtx->coded_height);
505 retry_decode_open = 0;
506 }
507 av_hwframe_constraints_free(&constraints);
508 if (hwconfig) {
509 av_freep(&hwconfig);
510 }
511 }
512 else {
513 int max_h, max_w;
514 //max_h = ((getenv( "LIMIT_HEIGHT_MAX" )==NULL) ? MAX_SUPPORTED_HEIGHT : atoi(getenv( "LIMIT_HEIGHT_MAX" )));
516 //max_w = ((getenv( "LIMIT_WIDTH_MAX" )==NULL) ? MAX_SUPPORTED_WIDTH : atoi(getenv( "LIMIT_WIDTH_MAX" )));
518 Logger::Instance()->AppendDebugMethod("Constraints could not be found using default limit\n");
519 //cerr << "Constraints could not be found using default limit\n";
520 if (pCodecCtx->coded_width < 0 ||
521 pCodecCtx->coded_height < 0 ||
522 pCodecCtx->coded_width > max_w ||
523 pCodecCtx->coded_height > max_h ) {
524 Logger::Instance()->AppendDebugMethod("DIMENSIONS ARE TOO LARGE for hardware acceleration\n", "Max Width :", max_w, "Max Height :", max_h, "Frame width :", pCodecCtx->coded_width, "Frame height :", pCodecCtx->coded_height);
525 hw_de_supported = 0;
526 retry_decode_open = 1;
527 AV_FREE_CONTEXT(pCodecCtx);
528 if (hw_device_ctx) {
529 av_buffer_unref(&hw_device_ctx);
530 hw_device_ctx = NULL;
531 }
532 }
533 else {
534 Logger::Instance()->AppendDebugMethod("\nDecode hardware acceleration is used\n", "Max Width :", max_w, "Max Height :", max_h, "Frame width :", pCodecCtx->coded_width, "Frame height :", pCodecCtx->coded_height);
535 retry_decode_open = 0;
536 }
537 }
538 } // if hw_de_on && hw_de_supported
539 else {
540 Logger::Instance()->AppendDebugMethod("\nDecode in software is used\n");
541 }
542#else
543 retry_decode_open = 0;
544#endif // USE_HW_ACCEL
545 } while (retry_decode_open); // retry_decode_open
546 // Free options
547 av_dict_free(&opts);
548
549 // Update the File Info struct with video details (if a video stream is found)
550 UpdateVideoInfo();
551 }
552
553 // Is there an audio stream?
554 if (audioStream != -1) {
555 // Set the stream index
556 info.audio_stream_index = audioStream;
557
558 // Get a pointer to the codec context for the audio stream
559 aStream = pFormatCtx->streams[audioStream];
560
561 // Find the codec ID from stream
562 AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(aStream);
563
564 // Get codec and codec context from stream
565 const AVCodec *aCodec = avcodec_find_decoder(codecId);
566 aCodecCtx = AV_GET_CODEC_CONTEXT(aStream, aCodec);
567
568 // Audio encoding does not typically use more than 2 threads (most codecs use 1 thread)
569 aCodecCtx->thread_count = std::min(FF_AUDIO_NUM_PROCESSORS, 2);
570
571 bool audio_opened = false;
572 if (aCodec != NULL) {
573 // Init options
574 AVDictionary *opts = NULL;
575 av_dict_set(&opts, "strict", "experimental", 0);
576
577 // Open audio codec
578 audio_opened = (avcodec_open2(aCodecCtx, aCodec, &opts) >= 0);
579
580 // Free options
581 av_dict_free(&opts);
582 }
583
584 if (audio_opened) {
585 // Update the File Info struct with audio details (if an audio stream is found)
586 UpdateAudioInfo();
587
588 // Disable malformed audio stream metadata (prevents divide-by-zero / invalid resampling math)
589 const bool invalid_audio_info =
590 (info.channels <= 0) ||
591 (info.sample_rate <= 0) ||
592 (info.audio_timebase.num <= 0) ||
593 (info.audio_timebase.den <= 0) ||
594 (aCodecCtx->sample_fmt == AV_SAMPLE_FMT_NONE);
595 if (invalid_audio_info) {
597 "FFmpegReader::Open (Disable invalid audio stream)",
598 "channels", info.channels,
599 "sample_rate", info.sample_rate,
600 "audio_timebase.num", info.audio_timebase.num,
601 "audio_timebase.den", info.audio_timebase.den,
602 "sample_fmt", static_cast<int>(aCodecCtx ? aCodecCtx->sample_fmt : AV_SAMPLE_FMT_NONE));
603 info.has_audio = false;
605 audioStream = -1;
606 packet_status.audio_eof = true;
607 if (aCodecCtx) {
608 if (avcodec_is_open(aCodecCtx)) {
609 avcodec_flush_buffers(aCodecCtx);
610 }
611 AV_FREE_CONTEXT(aCodecCtx);
612 aCodecCtx = nullptr;
613 }
614 aStream = nullptr;
615 }
616 } else {
617 // Keep decoding video, but disable bad/unsupported audio stream.
619 "FFmpegReader::Open (Audio codec unavailable; disabling audio)",
620 "audioStream", audioStream);
621 info.has_audio = false;
623 audioStream = -1;
624 packet_status.audio_eof = true;
625 if (aCodecCtx) {
626 AV_FREE_CONTEXT(aCodecCtx);
627 aCodecCtx = nullptr;
628 }
629 aStream = nullptr;
630 }
631 }
632
633 // Guard invalid frame-rate / timebase values from malformed streams.
634 if (info.fps.num <= 0 || info.fps.den <= 0) {
636 "FFmpegReader::Open (Invalid FPS detected; applying fallback)",
637 "fps.num", info.fps.num,
638 "fps.den", info.fps.den);
639 info.fps.num = 30;
640 info.fps.den = 1;
641 }
642 if (info.video_timebase.num <= 0 || info.video_timebase.den <= 0) {
644 "FFmpegReader::Open (Invalid video_timebase detected; applying fallback)",
645 "video_timebase.num", info.video_timebase.num,
646 "video_timebase.den", info.video_timebase.den);
648 }
649
650 // Add format metadata (if any)
651 AVDictionaryEntry *tag = NULL;
652 while ((tag = av_dict_get(pFormatCtx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
653 QString str_key = tag->key;
654 QString str_value = tag->value;
655 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
656 }
657
658 // Process video stream side data (rotation, spherical metadata, etc)
659 for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
660 AVStream* st = pFormatCtx->streams[i];
661 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
662 size_t side_data_size = 0;
663 const uint8_t *displaymatrix = ffmpeg_stream_get_side_data(
664 st, AV_PKT_DATA_DISPLAYMATRIX, &side_data_size);
665 if (displaymatrix &&
666 side_data_size >= 9 * sizeof(int32_t) &&
667 !info.metadata.count("rotate")) {
668 double rotation = -av_display_rotation_get(
669 reinterpret_cast<const int32_t *>(displaymatrix));
670 if (std::isnan(rotation))
671 rotation = 0;
672 info.metadata["rotate"] = std::to_string(rotation);
673 }
674
675 const uint8_t *spherical = ffmpeg_stream_get_side_data(
676 st, AV_PKT_DATA_SPHERICAL, &side_data_size);
677 if (spherical && side_data_size >= sizeof(AVSphericalMapping)) {
678 info.metadata["spherical"] = "1";
679
680 const AVSphericalMapping *map =
681 reinterpret_cast<const AVSphericalMapping *>(spherical);
682 const char *proj_name = av_spherical_projection_name(map->projection);
683 info.metadata["spherical_projection"] = proj_name ? proj_name : "unknown";
684
685 auto to_deg = [](int32_t v) {
686 return static_cast<double>(v) / 65536.0;
687 };
688 info.metadata["spherical_yaw"] = std::to_string(to_deg(map->yaw));
689 info.metadata["spherical_pitch"] = std::to_string(to_deg(map->pitch));
690 info.metadata["spherical_roll"] = std::to_string(to_deg(map->roll));
691 }
692 break;
693 }
694 }
695 UpdateOrientedVideoInfo();
696
697 // Init previous audio location to zero
698 previous_packet_location.frame = -1;
699 previous_packet_location.sample_start = 0;
700
701 // Adjust cache size based on size of frame and audio
702 const int working_cache_frames = std::max(Settings::Instance()->CACHE_MIN_FRAMES, int(OPEN_MP_NUM_PROCESSORS * info.fps.ToDouble() * 2));
703 const int final_cache_frames = std::max(Settings::Instance()->CACHE_MIN_FRAMES, OPEN_MP_NUM_PROCESSORS * 2);
704 working_cache.SetMaxBytesFromInfo(working_cache_frames, info.width, info.height, info.sample_rate, info.channels);
706
707 // Scan PTS for any offsets (i.e. non-zero starting streams). At least 1 stream must start at zero timestamp.
708 // This method allows us to shift timestamps to ensure at least 1 stream is starting at zero.
709 UpdatePTSOffset();
710
711 // Override an invalid framerate
712 if (info.fps.ToFloat() > 240.0f || (info.fps.num <= 0 || info.fps.den <= 0) || info.video_length <= 0) {
713 // Calculate FPS, duration, video bit rate, and video length manually
714 // by scanning through all the video stream packets
715 CheckFPS();
716 }
717
718 // Mark as "open"
719 is_open = true;
720
721 // Seek back to beginning of file (if not already seeking)
722 if (!is_seeking) {
723 Seek(1);
724 }
725 }
726}
727
729 // A queued close must not clean up contexts released by an earlier caller.
730 const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
731 // Close all objects, if reader is 'open'
732 if (is_open) {
733
734 // Mark as "closed"
735 is_open = false;
736
737 // Keep track of most recent packet
738 AVPacket *recent_packet = packet;
739
740 // Discard pending decoder output on close. Draining would allocate and
741 // cache frames that are immediately discarded, and can throw before
742 // resources are released (especially when closing under memory pressure).
743 packet = NULL;
744
745 // Remove packet
746 if (recent_packet) {
747 RemoveAVPacket(recent_packet);
748 }
749
750 // Close the video codec
751 if (info.has_video) {
752 if(avcodec_is_open(pCodecCtx)) {
753 avcodec_flush_buffers(pCodecCtx);
754 }
755 AV_FREE_CONTEXT(pCodecCtx);
756#if USE_HW_ACCEL
757 if (hw_de_on) {
758 if (hw_device_ctx) {
759 av_buffer_unref(&hw_device_ctx);
760 hw_device_ctx = NULL;
761 }
762 }
763#endif // USE_HW_ACCEL
764 if (img_convert_ctx) {
765 sws_freeContext(img_convert_ctx);
766 img_convert_ctx = nullptr;
767 }
768 if (pFrameRGB_cached) {
769 AV_FREE_FRAME(&pFrameRGB_cached);
770 }
771 }
772
773 // Close the audio codec
774 if (info.has_audio) {
775 if(avcodec_is_open(aCodecCtx)) {
776 avcodec_flush_buffers(aCodecCtx);
777 }
778 AV_FREE_CONTEXT(aCodecCtx);
779 if (avr_ctx) {
780 SWR_CLOSE(avr_ctx);
781 SWR_FREE(&avr_ctx);
782 avr_ctx = nullptr;
783 }
784 }
785
786 // Clear final cache
788 working_cache.Clear();
789
790 // Close the video file
791 avformat_close_input(&pFormatCtx);
792 av_freep(&pFormatCtx);
793
794 // Do not trim here; trimming is handled on explicit cache clears
795
796 // Reset some variables
797 last_frame = 0;
798 hold_packet = false;
799 largest_frame_processed = 0;
800 seek_audio_frame_found = 0;
801 seek_video_frame_found = 0;
802 current_video_frame = 0;
803 first_video_frame = 0;
804 last_video_frame.reset();
805 last_final_video_frame.reset();
806 }
807}
808
809bool FFmpegReader::HasAlbumArt() {
810 // Check if the video stream we use is an attached picture
811 // This won't return true if the file has a cover image as a secondary stream
812 // like an MKV file with an attached image file
813 return pFormatCtx && videoStream >= 0 && pFormatCtx->streams[videoStream]
814 && (pFormatCtx->streams[videoStream]->disposition & AV_DISPOSITION_ATTACHED_PIC);
815}
816
817double FFmpegReader::PickDurationSeconds() const {
818 auto has_value = [](double value) { return value > 0.0; };
819
820 switch (duration_strategy) {
822 if (has_value(video_stream_duration_seconds))
823 return video_stream_duration_seconds;
824 if (has_value(audio_stream_duration_seconds))
825 return audio_stream_duration_seconds;
826 if (has_value(format_duration_seconds))
827 return format_duration_seconds;
828 break;
830 if (has_value(audio_stream_duration_seconds))
831 return audio_stream_duration_seconds;
832 if (has_value(video_stream_duration_seconds))
833 return video_stream_duration_seconds;
834 if (has_value(format_duration_seconds))
835 return format_duration_seconds;
836 break;
838 default:
839 {
840 double longest = 0.0;
841 if (has_value(video_stream_duration_seconds))
842 longest = std::max(longest, video_stream_duration_seconds);
843 if (has_value(audio_stream_duration_seconds))
844 longest = std::max(longest, audio_stream_duration_seconds);
845 if (has_value(format_duration_seconds))
846 longest = std::max(longest, format_duration_seconds);
847 if (has_value(longest))
848 return longest;
849 }
850 break;
851 }
852
853 if (has_value(format_duration_seconds))
854 return format_duration_seconds;
855 if (has_value(inferred_duration_seconds))
856 return inferred_duration_seconds;
857
858 return 0.0;
859}
860
861void FFmpegReader::ApplyDurationStrategy() {
862 const double fps_value = info.fps.ToDouble();
863 const double chosen_seconds = PickDurationSeconds();
864
865 if (chosen_seconds <= 0.0 || fps_value <= 0.0) {
866 info.duration = 0.0f;
867 info.video_length = 0;
868 is_duration_known = false;
869 return;
870 }
871
872 const int64_t frames = static_cast<int64_t>(std::llround(chosen_seconds * fps_value));
873 if (frames <= 0) {
874 info.duration = 0.0f;
875 info.video_length = 0;
876 is_duration_known = false;
877 return;
878 }
879
880 info.video_length = frames;
881 info.duration = static_cast<float>(static_cast<double>(frames) / fps_value);
882 is_duration_known = true;
883}
884
885void FFmpegReader::UpdateAudioInfo() {
886 int codec_channels =
887#if HAVE_CH_LAYOUT
888 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout.nb_channels;
889#else
890 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
891#endif
892
893 // Set default audio channel layout (if needed)
894#if HAVE_CH_LAYOUT
895 AVChannelLayout audio_ch_layout = ffmpeg_get_valid_channel_layout(
896 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout, codec_channels);
897 if (audio_ch_layout.nb_channels > 0) {
898 av_channel_layout_uninit(&(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout));
899 av_channel_layout_copy(&(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout), &audio_ch_layout);
900 codec_channels = audio_ch_layout.nb_channels;
901 }
902#else
903 if (codec_channels > 0 && AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout == 0)
904 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout = av_get_default_channel_layout(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels);
905#endif
906
907 if (info.sample_rate > 0) {
908 // Skip init - if info struct already populated
909 return;
910 }
911
912 auto record_duration = [](double &target, double seconds) {
913 if (seconds > 0.0)
914 target = std::max(target, seconds);
915 };
916
917 // Set values of FileInfo struct
918 info.has_audio = true;
919 info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
920 info.acodec = aCodecCtx->codec->name;
921#if HAVE_CH_LAYOUT
922 info.channels = audio_ch_layout.nb_channels;
923 info.channel_layout = static_cast<ChannelLayout>(ffmpeg_channel_layout_mask(audio_ch_layout));
924#else
925 info.channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
926 info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout;
927#endif
928
929 // If channel layout is not set, guess based on the number of channels
930 if (info.channel_layout == 0) {
931 if (info.channels == 1) {
933 } else if (info.channels == 2) {
935 }
936 }
937
938 info.sample_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->sample_rate;
939 info.audio_bit_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->bit_rate;
940 if (info.audio_bit_rate <= 0) {
941 // Get bitrate from format
942 info.audio_bit_rate = pFormatCtx->bit_rate;
943 }
944
945 // Set audio timebase
946 info.audio_timebase.num = aStream->time_base.num;
947 info.audio_timebase.den = aStream->time_base.den;
948
949 // Get timebase of audio stream (if valid) and greater than the current duration
950 if (aStream->duration > 0) {
951 record_duration(audio_stream_duration_seconds, aStream->duration * info.audio_timebase.ToDouble());
952 }
953 if (pFormatCtx->duration > 0) {
954 // Use the format's duration when stream duration is missing or shorter
955 record_duration(format_duration_seconds, static_cast<double>(pFormatCtx->duration) / AV_TIME_BASE);
956 }
957
958 // Calculate duration from filesize and bitrate (if any)
959 if (info.duration <= 0.0f && info.video_bit_rate > 0 && info.file_size > 0) {
960 // Estimate from bitrate, total bytes, and framerate
961 record_duration(inferred_duration_seconds, static_cast<double>(info.file_size) / info.video_bit_rate);
962 }
963
964 // Set video timebase (if no video stream was found)
965 if (!info.has_video) {
966 // Set a few important default video settings (so audio can be divided into frames)
967 info.fps.num = 30;
968 info.fps.den = 1;
971 if (info.width <= 0 || info.height <= 0) {
972 info.width = 720;
973 info.height = 480;
974 }
975
976 // Use timeline to set correct width & height (if any)
977 Clip *parent = static_cast<Clip *>(ParentClip());
978 if (parent) {
979 if (parent->ParentTimeline()) {
980 // Set max width/height based on parent clip's timeline (if attached to a timeline)
983 }
984 }
985 }
986
987 ApplyDurationStrategy();
988
989 // Add audio metadata (if any found)
990 AVDictionaryEntry *tag = NULL;
991 while ((tag = av_dict_get(aStream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
992 QString str_key = tag->key;
993 QString str_value = tag->value;
994 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
995 }
996#if HAVE_CH_LAYOUT
997 av_channel_layout_uninit(&audio_ch_layout);
998#endif
999}
1000
1001void FFmpegReader::UpdateVideoInfo() {
1002 if (info.vcodec.length() > 0) {
1003 // JSON-loaded readers may already have display-oriented info populated,
1004 // but decoding still needs the raw stream dimensions for orientation.
1005 if (info.has_video && pStream && pCodecCtx) {
1006 source_height = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->height;
1007 source_width = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->width;
1008 UpdateOrientedVideoInfo();
1009 }
1010 return;
1011 }
1012
1013 auto record_duration = [](double &target, double seconds) {
1014 if (seconds > 0.0)
1015 target = std::max(target, seconds);
1016 };
1017
1018 // Set values of FileInfo struct
1019 info.has_video = true;
1020 info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
1021 source_height = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->height;
1022 source_width = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->width;
1023 info.height = source_height;
1024 info.width = source_width;
1025 info.vcodec = pCodecCtx->codec->name;
1026 info.video_bit_rate = (pFormatCtx->bit_rate / 8);
1027
1028 // Frame rate from the container and codec
1029 AVRational framerate = av_guess_frame_rate(pFormatCtx, pStream, NULL);
1030 if (!check_fps) {
1031 info.fps.num = framerate.num;
1032 info.fps.den = framerate.den;
1033 }
1034
1035 Logger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo", "info.fps.num", info.fps.num, "info.fps.den", info.fps.den);
1036
1037 // TODO: remove excessive debug info in the next releases
1038 // The debug info below is just for comparison and troubleshooting on users side during the transition period
1039 Logger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo (pStream->avg_frame_rate)", "num", pStream->avg_frame_rate.num, "den", pStream->avg_frame_rate.den);
1040
1041 if (pStream->sample_aspect_ratio.num != 0) {
1042 info.pixel_ratio.num = pStream->sample_aspect_ratio.num;
1043 info.pixel_ratio.den = pStream->sample_aspect_ratio.den;
1044 } else if (AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num != 0) {
1045 info.pixel_ratio.num = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num;
1046 info.pixel_ratio.den = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.den;
1047 } else {
1048 info.pixel_ratio.num = 1;
1049 info.pixel_ratio.den = 1;
1050 }
1051 info.pixel_format = AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
1052
1053 // Calculate the DAR (display aspect ratio)
1055
1056 // Reduce size fraction
1057 size.Reduce();
1058
1059 // Set the ratio based on the reduced fraction
1060 info.display_ratio.num = size.num;
1061 info.display_ratio.den = size.den;
1062
1063 // Get scan type and order from codec context/params
1064 if (!check_interlace) {
1065 check_interlace = true;
1066 AVFieldOrder field_order = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->field_order;
1067 switch(field_order) {
1068 case AV_FIELD_PROGRESSIVE:
1069 info.interlaced_frame = false;
1070 break;
1071 case AV_FIELD_TT:
1072 case AV_FIELD_TB:
1073 info.interlaced_frame = true;
1074 info.top_field_first = true;
1075 break;
1076 case AV_FIELD_BT:
1077 case AV_FIELD_BB:
1078 info.interlaced_frame = true;
1079 info.top_field_first = false;
1080 break;
1081 case AV_FIELD_UNKNOWN:
1082 // Check again later?
1083 check_interlace = false;
1084 break;
1085 }
1086 // check_interlace will prevent these checks being repeated,
1087 // unless it was cleared because we got an AV_FIELD_UNKNOWN response.
1088 }
1089
1090 // Set the video timebase
1091 info.video_timebase.num = pStream->time_base.num;
1092 info.video_timebase.den = pStream->time_base.den;
1093
1094 // Set the duration in seconds, and video length (# of frames)
1095 record_duration(video_stream_duration_seconds, pStream->duration * info.video_timebase.ToDouble());
1096
1097 // Check for valid duration (if found)
1098 if (pFormatCtx->duration >= 0) {
1099 // Use the format's duration as another candidate
1100 record_duration(format_duration_seconds, static_cast<double>(pFormatCtx->duration) / AV_TIME_BASE);
1101 }
1102
1103 // Calculate duration from filesize and bitrate (if any)
1104 if (info.video_bit_rate > 0 && info.file_size > 0) {
1105 // Estimate from bitrate, total bytes, and framerate
1106 record_duration(inferred_duration_seconds, static_cast<double>(info.file_size) / info.video_bit_rate);
1107 }
1108
1109 // Certain "image" formats do not have a valid duration
1110 if (video_stream_duration_seconds <= 0.0 && format_duration_seconds <= 0.0 &&
1111 pStream->duration == AV_NOPTS_VALUE && pFormatCtx->duration == AV_NOPTS_VALUE) {
1112 // Force an "image" duration
1113 record_duration(video_stream_duration_seconds, 60 * 60 * 1); // 1 hour duration
1114 info.has_single_image = true;
1115 }
1116 // Static GIFs can have no usable duration; fall back to a small default
1117 if (video_stream_duration_seconds <= 0.0 && format_duration_seconds <= 0.0 &&
1118 pFormatCtx && pFormatCtx->iformat && strcmp(pFormatCtx->iformat->name, "gif") == 0) {
1119 record_duration(video_stream_duration_seconds, 60 * 60 * 1); // 1 hour duration
1120 info.has_single_image = true;
1121 }
1122
1123 ApplyDurationStrategy();
1124
1125 // Normalize FFmpeg-decoded still images (e.g. JPG/JPEG) to match image-reader behavior.
1126 // This keeps timing/flags consistent regardless of which reader path was used.
1127 if (!info.has_single_image) {
1128 const AVCodecID codec_id = AV_FIND_DECODER_CODEC_ID(pStream);
1129 const bool likely_still_codec =
1130 codec_id == AV_CODEC_ID_MJPEG ||
1131 codec_id == AV_CODEC_ID_PNG ||
1132 codec_id == AV_CODEC_ID_BMP ||
1133 codec_id == AV_CODEC_ID_TIFF ||
1134 codec_id == AV_CODEC_ID_WEBP ||
1135 codec_id == AV_CODEC_ID_JPEG2000;
1136 const bool likely_image_demuxer =
1137 pFormatCtx && pFormatCtx->iformat && pFormatCtx->iformat->name &&
1138 strstr(pFormatCtx->iformat->name, "image2");
1139 const bool has_attached_pic = HasAlbumArt();
1140 const bool single_frame_stream =
1141 (pStream && pStream->nb_frames > 0 && pStream->nb_frames <= 1);
1142 const bool single_frame_clip = info.video_length <= 1;
1143
1144 const bool is_still_image_video =
1145 has_attached_pic ||
1146 ((single_frame_stream || single_frame_clip) &&
1147 (likely_still_codec || likely_image_demuxer));
1148
1149 if (is_still_image_video) {
1150 info.has_single_image = true;
1151
1152 // Only force long duration for standalone images. For audio + attached-art
1153 // files, keep stream-derived duration so the cover image spans the audio.
1154 if (audioStream < 0) {
1155 record_duration(video_stream_duration_seconds, 60 * 60 * 1); // 1 hour duration
1156 }
1157
1158 ApplyDurationStrategy();
1159 }
1160 }
1161
1162 // Add video metadata (if any)
1163 AVDictionaryEntry *tag = NULL;
1164 while ((tag = av_dict_get(pStream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
1165 QString str_key = tag->key;
1166 QString str_value = tag->value;
1167 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
1168 }
1169
1170 UpdateOrientedVideoInfo();
1171}
1172
1173void FFmpegReader::UpdateOrientedVideoInfo() {
1175 return;
1176
1177 if (source_width <= 0 || source_height <= 0) {
1178 source_width = info.width;
1179 source_height = info.height;
1180 }
1181 if (source_width <= 0 || source_height <= 0)
1182 return;
1183
1184 source_rotation = 0.0;
1185 const auto rotate_meta = info.metadata.find("rotate");
1186 if (rotate_meta != info.metadata.end())
1187 source_rotation = strtod(rotate_meta->second.c_str(), nullptr);
1188
1189 const double radians = source_rotation * M_PI / 180.0;
1190 const int oriented_width = static_cast<int>(std::round(
1191 std::fabs(source_width * std::cos(radians)) +
1192 std::fabs(source_height * std::sin(radians))));
1193 const int oriented_height = static_cast<int>(std::round(
1194 std::fabs(source_width * std::sin(radians)) +
1195 std::fabs(source_height * std::cos(radians))));
1196
1197 if (oriented_width > 0 && oriented_height > 0) {
1198 info.width = oriented_width;
1199 info.height = oriented_height;
1200
1202 size.Reduce();
1203 info.display_ratio.num = size.num;
1204 info.display_ratio.den = size.den;
1205 }
1206}
1207
1208void FFmpegReader::ApplyFrameOrientation(std::shared_ptr<openshot::Frame> frame) {
1209 if (!ApplyOrientationMetadata() || std::fabs(source_rotation) < 0.0001 || !frame || !frame->has_image_data)
1210 return;
1211
1212 auto image = frame->GetImage();
1213 if (!image || image->isNull())
1214 return;
1215
1216 QImage oriented = image->transformed(QTransform().rotate(source_rotation), Qt::SmoothTransformation);
1217 frame->AddImage(std::make_shared<QImage>(oriented));
1218}
1219
1221 return this->is_duration_known;
1222}
1223
1224std::shared_ptr<Frame> FFmpegReader::GetFrame(int64_t requested_frame) {
1225 last_seek_max_frame = -1;
1226 seek_stagnant_count = 0;
1227 // Check for open reader (or throw exception)
1228 if (!is_open)
1229 throw ReaderClosed("The FFmpegReader is closed. Call Open() before calling this method.", path);
1230
1231 // Adjust for a requested frame that is too small or too large
1232 if (requested_frame < 1)
1233 requested_frame = 1;
1234 if (requested_frame > info.video_length && is_duration_known)
1235 requested_frame = info.video_length;
1236 if (info.has_video && info.video_length == 0)
1237 // Invalid duration of video file
1238 throw InvalidFile("Could not detect the duration of the video or audio stream.", path);
1239
1240 // Debug output
1241 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "requested_frame", requested_frame, "last_frame", last_frame);
1242
1243 // Check the cache for this frame
1244 std::shared_ptr<Frame> frame = final_cache.GetFrame(requested_frame);
1245 if (frame) {
1246 // Debug output
1247 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "returned cached frame", requested_frame);
1248 // Return the cached frame
1249 return frame;
1250 } else {
1251
1252 // Prevent async calls to the remainder of this code
1253 const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
1254
1255 // Check the cache a 2nd time (due to the potential previous lock)
1256 frame = final_cache.GetFrame(requested_frame);
1257 if (frame) {
1258 // Debug output
1259 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "returned cached frame on 2nd look", requested_frame);
1260 } else {
1261 // Frame is not in cache
1262 // Reset seek count
1263 seek_count = 0;
1264
1265 // Are we within X frames of the requested frame?
1266 int64_t diff = requested_frame - last_frame;
1267 if (diff >= 1 && diff <= 20) {
1268 // Continue walking the stream
1269 frame = ReadStream(requested_frame);
1270 } else {
1271 // Greater than 30 frames away, or backwards, we need to seek to the nearest key frame
1272 if (enable_seek) {
1273 // Only seek if enabled
1274 Seek(requested_frame);
1275
1276 } else if (!enable_seek && diff < 0) {
1277 // Start over, since we can't seek, and the requested frame is smaller than our position
1278 // Since we are seeking to frame 1, this actually just closes/re-opens the reader
1279 Seek(1);
1280 }
1281
1282 // Then continue walking the stream
1283 frame = ReadStream(requested_frame);
1284 }
1285 }
1286 return frame;
1287 }
1288}
1289
1290// Read the stream until we find the requested Frame
1291std::shared_ptr<Frame> FFmpegReader::ReadStream(int64_t requested_frame) {
1292 // Allocate video frame
1293 bool check_seek = false;
1294 int packet_error = -1;
1295 int64_t no_progress_count = 0;
1296 int64_t prev_packets_read = packet_status.packets_read();
1297 int64_t prev_packets_decoded = packet_status.packets_decoded();
1298 int64_t prev_video_decoded = packet_status.video_decoded;
1299 double prev_video_pts_seconds = video_pts_seconds;
1300
1301 // Debug output
1302 Logger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream", "requested_frame", requested_frame);
1303
1304 // Loop through the stream until the correct frame is found
1305 while (true) {
1306 // Check if working frames are 'finished'
1307 if (!is_seeking) {
1308 // Check for final frames
1309 CheckWorkingFrames(requested_frame);
1310 }
1311
1312 // Check if requested 'final' frame is available (and break out of loop if found)
1313 bool is_cache_found = (final_cache.GetFrame(requested_frame) != NULL);
1314 if (is_cache_found) {
1315 break;
1316 }
1317
1318 if (!hold_packet || !packet) {
1319 // Get the next packet
1320 packet_error = GetNextPacket();
1321 if (packet_error < 0 && !packet) {
1322 // No more packets to be found
1323 packet_status.packets_eof = true;
1324 }
1325 }
1326
1327 // Debug output
1328 Logger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (GetNextPacket)", "requested_frame", requested_frame,"packets_read", packet_status.packets_read(), "packets_decoded", packet_status.packets_decoded(), "is_seeking", is_seeking);
1329
1330 // Check the status of a seek (if any)
1331 if (is_seeking) {
1332 check_seek = CheckSeek();
1333 } else {
1334 check_seek = false;
1335 }
1336
1337 if (check_seek) {
1338 // Packet may become NULL on Close inside Seek if CheckSeek returns false
1339 // Jump to the next iteration of this loop
1340 continue;
1341 }
1342
1343 // Video packet
1344 if ((info.has_video && packet && packet->stream_index == videoStream) ||
1345 (info.has_video && packet_status.video_decoded < packet_status.video_read) ||
1346 (info.has_video && !packet && !packet_status.video_eof)) {
1347 // Process Video Packet
1348 ProcessVideoPacket(requested_frame);
1349 if (ReopenWithoutHardwareDecode(requested_frame)) {
1350 continue;
1351 }
1352 }
1353 // Audio packet
1354 if ((info.has_audio && packet && packet->stream_index == audioStream) ||
1355 (info.has_audio && !packet && packet_status.audio_decoded < packet_status.audio_read) ||
1356 (info.has_audio && !packet && !packet_status.audio_eof)) {
1357 // Process Audio Packet
1358 ProcessAudioPacket(requested_frame);
1359 }
1360
1361 // Remove unused packets (sometimes we purposely ignore video or audio packets,
1362 // if the has_video or has_audio properties are manually overridden)
1363 if ((!info.has_video && packet && packet->stream_index == videoStream) ||
1364 (!info.has_audio && packet && packet->stream_index == audioStream)) {
1365 // Keep track of deleted packet counts
1366 if (packet->stream_index == videoStream) {
1367 packet_status.video_decoded++;
1368 } else if (packet->stream_index == audioStream) {
1369 packet_status.audio_decoded++;
1370 }
1371
1372 // Remove unused packets (sometimes we purposely ignore video or audio packets,
1373 // if the has_video or has_audio properties are manually overridden)
1374 RemoveAVPacket(packet);
1375 packet = NULL;
1376 }
1377
1378 // Determine end-of-stream (waiting until final decoder threads finish)
1379 // Force end-of-stream in some situations
1380 packet_status.end_of_file = packet_status.packets_eof && packet_status.video_eof && packet_status.audio_eof;
1381 if ((packet_status.packets_eof && packet_status.packets_read() == packet_status.packets_decoded()) || packet_status.end_of_file) {
1382 // Force EOF (end of file) variables to true, if decoder does not support EOF detection.
1383 // If we have no more packets, and all known packets have been decoded
1384 Logger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (force EOF)", "packets_read", packet_status.packets_read(), "packets_decoded", packet_status.packets_decoded(), "packets_eof", packet_status.packets_eof, "video_eof", packet_status.video_eof, "audio_eof", packet_status.audio_eof, "end_of_file", packet_status.end_of_file);
1385 if (!packet_status.video_eof) {
1386 packet_status.video_eof = true;
1387 }
1388 if (!packet_status.audio_eof) {
1389 packet_status.audio_eof = true;
1390 }
1391 packet_status.end_of_file = true;
1392 break;
1393 }
1394
1395 // Detect decoder stalls with no progress at EOF and force completion so
1396 // missing frames can be finalized from prior image data.
1397 const bool has_progress =
1398 (packet_status.packets_read() != prev_packets_read) ||
1399 (packet_status.packets_decoded() != prev_packets_decoded) ||
1400 (packet_status.video_decoded != prev_video_decoded) ||
1401 (video_pts_seconds != prev_video_pts_seconds);
1402
1403 if (has_progress) {
1404 no_progress_count = 0;
1405 } else {
1406 no_progress_count++;
1407 if (no_progress_count >= 2000
1408 && packet_status.packets_eof
1409 && !packet
1410 && !hold_packet) {
1411 Logger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (force EOF after stall)",
1412 "requested_frame", requested_frame,
1413 "no_progress_count", no_progress_count,
1414 "packets_read", packet_status.packets_read(),
1415 "packets_decoded", packet_status.packets_decoded(),
1416 "video_decoded", packet_status.video_decoded,
1417 "audio_decoded", packet_status.audio_decoded);
1418 packet_status.video_eof = true;
1419 packet_status.audio_eof = true;
1420 packet_status.end_of_file = true;
1421 break;
1422 }
1423 }
1424 prev_packets_read = packet_status.packets_read();
1425 prev_packets_decoded = packet_status.packets_decoded();
1426 prev_video_decoded = packet_status.video_decoded;
1427 prev_video_pts_seconds = video_pts_seconds;
1428 } // end while
1429
1430 // Debug output
1431 Logger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (Completed)",
1432 "packets_read", packet_status.packets_read(),
1433 "packets_decoded", packet_status.packets_decoded(),
1434 "end_of_file", packet_status.end_of_file,
1435 "largest_frame_processed", largest_frame_processed,
1436 "Working Cache Count", working_cache.Count());
1437
1438 // Have we reached end-of-stream (or the final frame)?
1439 if (!packet_status.end_of_file && requested_frame >= info.video_length) {
1440 // Force end-of-stream
1441 packet_status.end_of_file = true;
1442 }
1443 if (packet_status.end_of_file) {
1444 // Mark any other working frames as 'finished'
1445 CheckWorkingFrames(requested_frame);
1446 }
1447
1448 // Return requested frame (if found)
1449 std::shared_ptr<Frame> frame = final_cache.GetFrame(requested_frame);
1450 if (frame)
1451 // Return prepared frame
1452 return frame;
1453 else {
1454
1455 // Check if largest frame is still cached
1456 frame = final_cache.GetFrame(largest_frame_processed);
1457 int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, info.fps,
1459 if (frame) {
1460 // Copy and return the largest processed frame (assuming it was the last in the video file)
1461 std::shared_ptr<Frame> f = CreateFrame(largest_frame_processed);
1462 if (frame->has_image_data) {
1463 f->AddImage(std::make_shared<QImage>(frame->GetImage()->copy()));
1464 }
1465
1466 // Use solid color (if no image data found)
1467 if (!frame->has_image_data) {
1468 // Use solid black frame if no image data available
1469 f->AddColor(info.width, info.height, "#000");
1470 }
1471 // Silence audio data (if any), since we are repeating the last frame
1472 f->AddAudioSilence(samples_in_frame);
1473
1474 return f;
1475 } else {
1476 // The largest processed frame is no longer in cache. Prefer the most recent
1477 // finalized image first, then decoded image, to avoid black flashes.
1478 std::shared_ptr<Frame> f = CreateFrame(largest_frame_processed);
1479 if (last_final_video_frame && last_final_video_frame->has_image_data
1480 && last_final_video_frame->number <= requested_frame) {
1481 f->AddImage(std::make_shared<QImage>(last_final_video_frame->GetImage()->copy()));
1482 } else if (last_video_frame && last_video_frame->has_image_data
1483 && last_video_frame->number <= requested_frame) {
1484 f->AddImage(std::make_shared<QImage>(last_video_frame->GetImage()->copy()));
1485 } else {
1486 f->AddColor(info.width, info.height, "#000");
1487 }
1488 f->AddAudioSilence(samples_in_frame);
1489 return f;
1490 }
1491 }
1492
1493}
1494
1495// Get the next packet (if any)
1496int FFmpegReader::GetNextPacket() {
1497 int found_packet = 0;
1498 AVPacket *next_packet;
1499 next_packet = new AVPacket();
1500 found_packet = av_read_frame(pFormatCtx, next_packet);
1501
1502 if (packet) {
1503 // Remove previous packet before getting next one
1504 RemoveAVPacket(packet);
1505 packet = NULL;
1506 }
1507 if (found_packet >= 0) {
1508 // Update current packet pointer
1509 packet = next_packet;
1510
1511 // Keep track of packet stats
1512 if (packet->stream_index == videoStream) {
1513 packet_status.video_read++;
1514 } else if (packet->stream_index == audioStream) {
1515 packet_status.audio_read++;
1516 }
1517 } else {
1518 // No more packets found
1519 delete next_packet;
1520 packet = NULL;
1521 }
1522 // Return if packet was found (or error number)
1523 return found_packet;
1524}
1525
1526// Get an AVFrame (if any)
1527bool FFmpegReader::GetAVFrame() {
1528 int frameFinished = 0;
1529 auto note_hw_decode_failure = [&](int err, const char* stage) {
1530#if USE_HW_ACCEL
1531 if (!hw_de_on || !hw_de_supported || force_sw_decode) {
1532 return;
1533 }
1534 if (err == AVERROR_INVALIDDATA && packet_status.video_decoded == 0) {
1535 hw_decode_error_count++;
1537 std::string("FFmpegReader::GetAVFrame (hardware decode failure candidate during ") + stage + ")",
1538 "error_count", hw_decode_error_count,
1539 "error", err);
1540 if (hw_decode_error_count >= 3) {
1541 hw_decode_failed = true;
1542 }
1543 }
1544#else
1545 (void) err;
1546 (void) stage;
1547#endif
1548 };
1549
1550 // Decode video frame
1551 AVFrame *next_frame = AV_ALLOCATE_FRAME();
1552
1553#if IS_FFMPEG_3_2
1554 int send_packet_err = 0;
1555 int64_t send_packet_pts = 0;
1556 if ((packet && packet->stream_index == videoStream) || !packet) {
1557 send_packet_err = avcodec_send_packet(pCodecCtx, packet);
1558
1559 if (packet && send_packet_err >= 0) {
1560 send_packet_pts = GetPacketPTS();
1561 hold_packet = false;
1562 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (send packet succeeded)", "send_packet_err", send_packet_err, "send_packet_pts", send_packet_pts);
1563 }
1564 }
1565
1566 #if USE_HW_ACCEL
1567 // Get the format from the variables set in get_hw_dec_format
1568 hw_de_av_pix_fmt = hw_de_av_pix_fmt_global;
1569 hw_de_av_device_type = hw_de_av_device_type_global;
1570 #endif // USE_HW_ACCEL
1571 if (send_packet_err < 0 && send_packet_err != AVERROR_EOF) {
1572 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (send packet: Not sent [" + av_err2string(send_packet_err) + "])", "send_packet_err", send_packet_err, "send_packet_pts", send_packet_pts);
1573 note_hw_decode_failure(send_packet_err, "send_packet");
1574 if (send_packet_err == AVERROR(EAGAIN)) {
1575 hold_packet = true;
1576 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (send packet: AVERROR(EAGAIN): user must read output with avcodec_receive_frame()", "send_packet_pts", send_packet_pts);
1577 }
1578 if (send_packet_err == AVERROR(EINVAL)) {
1579 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (send packet: AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush", "send_packet_pts", send_packet_pts);
1580 }
1581 if (send_packet_err == AVERROR(ENOMEM)) {
1582 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (send packet: AVERROR(ENOMEM): failed to add packet to internal queue, or legitimate decoding errors", "send_packet_pts", send_packet_pts);
1583 }
1584 }
1585
1586 // Always try and receive a packet, if not EOF.
1587 // Even if the above avcodec_send_packet failed to send,
1588 // we might still need to receive a packet.
1589 int receive_frame_err = 0;
1590 AVFrame *decoded_frame = next_frame;
1591 AVFrame *next_frame2;
1592#if USE_HW_ACCEL
1593 if (hw_de_on && hw_de_supported) {
1594 next_frame2 = AV_ALLOCATE_FRAME();
1595 }
1596 else
1597#endif // USE_HW_ACCEL
1598 {
1599 next_frame2 = next_frame;
1600 }
1601 pFrame = AV_ALLOCATE_FRAME();
1602 while (receive_frame_err >= 0) {
1603 receive_frame_err = avcodec_receive_frame(pCodecCtx, next_frame2);
1604
1605 if (receive_frame_err != 0) {
1606 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (receive frame: frame not ready yet from decoder [\" + av_err2string(receive_frame_err) + \"])", "receive_frame_err", receive_frame_err, "send_packet_pts", send_packet_pts);
1607 note_hw_decode_failure(receive_frame_err, "receive_frame");
1608
1609 if (receive_frame_err == AVERROR_EOF) {
1611 "FFmpegReader::GetAVFrame (receive frame: AVERROR_EOF: EOF detected from decoder, flushing buffers)", "send_packet_pts", send_packet_pts);
1612 avcodec_flush_buffers(pCodecCtx);
1613 packet_status.video_eof = true;
1614 }
1615 if (receive_frame_err == AVERROR(EINVAL)) {
1617 "FFmpegReader::GetAVFrame (receive frame: AVERROR(EINVAL): invalid frame received, flushing buffers)", "send_packet_pts", send_packet_pts);
1618 avcodec_flush_buffers(pCodecCtx);
1619 }
1620 if (receive_frame_err == AVERROR(EAGAIN)) {
1622 "FFmpegReader::GetAVFrame (receive frame: AVERROR(EAGAIN): output is not available in this state - user must try to send new input)", "send_packet_pts", send_packet_pts);
1623 }
1624 if (receive_frame_err == AVERROR_INPUT_CHANGED) {
1626 "FFmpegReader::GetAVFrame (receive frame: AVERROR_INPUT_CHANGED: current decoded frame has changed parameters with respect to first decoded frame)", "send_packet_pts", send_packet_pts);
1627 }
1628
1629 // Break out of decoding loop
1630 // Nothing ready for decoding yet
1631 break;
1632 }
1633
1634#if USE_HW_ACCEL
1635 if (hw_de_on && hw_de_supported) {
1636 int err;
1637 if (next_frame2->format == hw_de_av_pix_fmt) {
1638 if ((err = av_hwframe_transfer_data(next_frame, next_frame2, 0)) < 0) {
1640 "FFmpegReader::GetAVFrame (Failed to transfer data to output frame)",
1641 "hw_de_on", hw_de_on,
1642 "error", err);
1643 note_hw_decode_failure(AVERROR_INVALIDDATA, "hwframe_transfer");
1644 break;
1645 }
1646 if ((err = av_frame_copy_props(next_frame, next_frame2)) < 0) {
1648 "FFmpegReader::GetAVFrame (Failed to copy props to output frame)",
1649 "hw_de_on", hw_de_on,
1650 "error", err);
1651 note_hw_decode_failure(AVERROR_INVALIDDATA, "hwframe_copy_props");
1652 break;
1653 }
1654 if (next_frame->format == AV_PIX_FMT_NONE) {
1655 next_frame->format = pCodecCtx->sw_pix_fmt;
1656 }
1657 if (next_frame->width <= 0) {
1658 next_frame->width = next_frame2->width;
1659 }
1660 if (next_frame->height <= 0) {
1661 next_frame->height = next_frame2->height;
1662 }
1663 decoded_frame = next_frame;
1664 } else {
1665 // Some hardware decoders can still return software-readable frames.
1666 decoded_frame = next_frame2;
1667 }
1668 }
1669 else
1670#endif // USE_HW_ACCEL
1671 { // No hardware acceleration used -> no copy from GPU memory needed
1672 decoded_frame = next_frame2;
1673 }
1674
1675 if (!decoded_frame->data[0]) {
1677 "FFmpegReader::GetAVFrame (Decoded frame missing image data)",
1678 "format", decoded_frame->format,
1679 "width", decoded_frame->width,
1680 "height", decoded_frame->height);
1681 note_hw_decode_failure(AVERROR_INVALIDDATA, "decoded_frame_empty");
1682 break;
1683 }
1684
1685 // TODO also handle possible further frames
1686 // Use only the first frame like avcodec_decode_video2
1687 frameFinished = 1;
1688 hw_decode_error_count = 0;
1689#if USE_HW_ACCEL
1690 if (hw_de_on && hw_de_supported && !force_sw_decode) {
1691 hw_decode_succeeded = true;
1692 }
1693#endif
1694 packet_status.video_decoded++;
1695
1696 // Allocate image (align 32 for simd)
1697 AVPixelFormat decoded_pix_fmt = (AVPixelFormat)(decoded_frame->format);
1698 if (decoded_pix_fmt == AV_PIX_FMT_NONE)
1699 decoded_pix_fmt = (AVPixelFormat)(pStream->codecpar->format);
1700 const int decoded_width = decoded_frame->width > 0 ? decoded_frame->width : info.width;
1701 const int decoded_height = decoded_frame->height > 0 ? decoded_frame->height : info.height;
1702 if (AV_ALLOCATE_IMAGE(pFrame, decoded_pix_fmt, decoded_width, decoded_height) <= 0) {
1703 throw OutOfMemory("Failed to allocate image buffer", path);
1704 }
1705 av_image_copy(pFrame->data, pFrame->linesize, (const uint8_t**)decoded_frame->data, decoded_frame->linesize,
1706 decoded_pix_fmt, decoded_width, decoded_height);
1707 pFrame->format = decoded_pix_fmt;
1708 pFrame->width = decoded_width;
1709 pFrame->height = decoded_height;
1710 pFrame->color_range = decoded_frame->color_range;
1711 pFrame->colorspace = decoded_frame->colorspace;
1712 pFrame->color_primaries = decoded_frame->color_primaries;
1713 pFrame->color_trc = decoded_frame->color_trc;
1714 pFrame->chroma_location = decoded_frame->chroma_location;
1715
1716 // Get display PTS from video frame, often different than packet->pts.
1717 // Sending packets to the decoder (i.e. packet->pts) is async,
1718 // and retrieving packets from the decoder (frame->pts) is async. In most decoders
1719 // sending and retrieving are separated by multiple calls to this method.
1720 if (decoded_frame->pts != AV_NOPTS_VALUE) {
1721 // This is the current decoded frame (and should be the pts used) for
1722 // processing this data
1723 video_pts = decoded_frame->pts;
1724 } else if (decoded_frame->pkt_dts != AV_NOPTS_VALUE) {
1725 // Some videos only set this timestamp (fallback)
1726 video_pts = decoded_frame->pkt_dts;
1727 }
1728
1730 "FFmpegReader::GetAVFrame (Successful frame received)", "video_pts", video_pts, "send_packet_pts", send_packet_pts);
1731
1732 // break out of loop after each successful image returned
1733 break;
1734 }
1735#if USE_HW_ACCEL
1736 if (hw_de_on && hw_de_supported && next_frame2 != next_frame) {
1737 AV_FREE_FRAME(&next_frame2);
1738 }
1739 #endif // USE_HW_ACCEL
1740#else
1741 avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
1742
1743 // always allocate pFrame (because we do that in the ffmpeg >= 3.2 as well); it will always be freed later
1744 pFrame = AV_ALLOCATE_FRAME();
1745
1746 // is frame finished
1747 if (frameFinished) {
1748 // AVFrames are clobbered on the each call to avcodec_decode_video, so we
1749 // must make a copy of the image data before this method is called again.
1750 avpicture_alloc((AVPicture *) pFrame, pCodecCtx->pix_fmt, info.width, info.height);
1751 av_picture_copy((AVPicture *) pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width,
1752 info.height);
1753 }
1754#endif // IS_FFMPEG_3_2
1755
1756 // deallocate the frame
1757 AV_FREE_FRAME(&next_frame);
1758
1759 // Did we get a video frame?
1760 return frameFinished;
1761}
1762
1763bool FFmpegReader::ReopenWithoutHardwareDecode(int64_t requested_frame) {
1764#if USE_HW_ACCEL
1765 if (!hw_decode_failed || force_sw_decode) {
1766 return false;
1767 }
1768
1770 "FFmpegReader::ReopenWithoutHardwareDecode (falling back to software decode)",
1771 "requested_frame", requested_frame,
1772 "video_packets_read", packet_status.video_read,
1773 "video_packets_decoded", packet_status.video_decoded,
1774 "hw_decode_error_count", hw_decode_error_count);
1775
1776 force_sw_decode = true;
1777 hw_decode_failed = false;
1778 hw_decode_error_count = 0;
1779
1780 Close();
1781 Open();
1782 Seek(requested_frame);
1783 return true;
1784#else
1785 (void) requested_frame;
1786 return false;
1787#endif
1788}
1789
1791#if USE_HW_ACCEL
1792 return hw_decode_succeeded;
1793#else
1794 return false;
1795#endif
1796}
1797
1798// Check the current seek position and determine if we need to seek again
1799bool FFmpegReader::CheckSeek() {
1800 // Are we seeking for a specific frame?
1801 if (is_seeking) {
1802 const int64_t kSeekRetryMax = 5;
1803 const int kSeekStagnantMax = 2;
1804
1805 // Determine if both an audio and video packet have been decoded since the seek happened.
1806 // If not, allow the ReadStream method to keep looping
1807 if ((is_video_seek && !seek_video_frame_found) || (!is_video_seek && !seek_audio_frame_found))
1808 return false;
1809
1810 // Check for both streams
1811 if ((info.has_video && !seek_video_frame_found) || (info.has_audio && !seek_audio_frame_found))
1812 return false;
1813
1814 // Determine max seeked frame
1815 int64_t max_seeked_frame = std::max(seek_audio_frame_found, seek_video_frame_found);
1816 // Track stagnant seek results (no progress between retries)
1817 if (max_seeked_frame == last_seek_max_frame) {
1818 seek_stagnant_count++;
1819 } else {
1820 last_seek_max_frame = max_seeked_frame;
1821 seek_stagnant_count = 0;
1822 }
1823
1824 // determine if we are "before" the requested frame
1825 if (max_seeked_frame >= seeking_frame) {
1826 // SEEKED TOO FAR
1827 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Too far, seek again)",
1828 "is_video_seek", is_video_seek,
1829 "max_seeked_frame", max_seeked_frame,
1830 "seeking_frame", seeking_frame,
1831 "seeking_pts", seeking_pts,
1832 "seek_video_frame_found", seek_video_frame_found,
1833 "seek_audio_frame_found", seek_audio_frame_found);
1834
1835 // Seek again... to the nearest Keyframe
1836 if (seek_count < kSeekRetryMax) {
1837 Seek(seeking_frame - (10 * seek_count * seek_count));
1838 } else if (seek_stagnant_count >= kSeekStagnantMax) {
1839 // Stagnant seek: force a much earlier target and keep seeking.
1840 Seek(seeking_frame - (10 * kSeekRetryMax * kSeekRetryMax));
1841 } else {
1842 // Retry budget exhausted: keep seeking from a conservative offset.
1843 Seek(seeking_frame - (10 * seek_count * seek_count));
1844 }
1845 } else {
1846 // SEEK WORKED
1847 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Successful)",
1848 "is_video_seek", is_video_seek,
1849 "packet->pts", GetPacketPTS(),
1850 "seeking_pts", seeking_pts,
1851 "seeking_frame", seeking_frame,
1852 "seek_video_frame_found", seek_video_frame_found,
1853 "seek_audio_frame_found", seek_audio_frame_found);
1854
1855 // Seek worked, and we are "before" the requested frame
1856 is_seeking = false;
1857 seeking_frame = 0;
1858 seeking_pts = -1;
1859 }
1860 }
1861
1862 // return the pts to seek to (if any)
1863 return is_seeking;
1864}
1865
1866// Process a video packet
1867void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
1868 // Get the AVFrame from the current packet
1869 // This sets the video_pts to the correct timestamp
1870 int frame_finished = GetAVFrame();
1871
1872 // Check if the AVFrame is finished and set it
1873 if (!frame_finished) {
1874 // No AVFrame decoded yet, bail out
1875 if (pFrame) {
1876 RemoveAVFrame(pFrame);
1877 }
1878 return;
1879 }
1880
1881 // Calculate current frame #
1882 int64_t current_frame = ConvertVideoPTStoFrame(video_pts);
1883
1884 // Track 1st video packet after a successful seek
1885 if (!seek_video_frame_found && is_seeking)
1886 seek_video_frame_found = current_frame;
1887
1888 // Create or get the existing frame object. Requested frame needs to be created
1889 // in working_cache at least once. Seek can clear the working_cache, so we must
1890 // add the requested frame back to the working_cache here. If it already exists,
1891 // it will be moved to the top of the working_cache.
1892 working_cache.Add(CreateFrame(requested_frame));
1893
1894 // Debug output
1895 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (Before)", "requested_frame", requested_frame, "current_frame", current_frame);
1896
1897 // Init some things local (for OpenMP)
1898 AVPixelFormat decoded_pix_fmt = (pFrame && pFrame->format != AV_PIX_FMT_NONE)
1899 ? static_cast<AVPixelFormat>(pFrame->format)
1900 : AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
1901 bool src_full_range = (pFrame && pFrame->color_range == AVCOL_RANGE_JPEG);
1902 AVPixelFormat src_pix_fmt = NormalizeDeprecatedPixFmt(decoded_pix_fmt, src_full_range);
1903 int src_width = (pFrame && pFrame->width > 0) ? pFrame->width : info.width;
1904 int src_height = (pFrame && pFrame->height > 0) ? pFrame->height : info.height;
1905 int height = src_height;
1906 int width = src_width;
1907 // Create or reuse a RGB Frame (since most videos are not in RGB, we must convert it)
1908 AVFrame *pFrameRGB = pFrameRGB_cached;
1909 if (!pFrameRGB) {
1910 pFrameRGB = AV_ALLOCATE_FRAME();
1911 if (pFrameRGB == nullptr)
1912 throw OutOfMemory("Failed to allocate frame buffer", path);
1913 pFrameRGB_cached = pFrameRGB;
1914 }
1915 AV_RESET_FRAME(pFrameRGB);
1916 uint8_t *buffer = nullptr;
1917
1918 // Determine the max size of this source image (based on the timeline's size, the scaling mode,
1919 // and the scaling keyframes). This is a performance improvement, to keep the images as small as possible,
1920 // without losing quality. NOTE: We cannot go smaller than the timeline itself, or the add_layer timeline
1921 // method will scale it back to timeline size before scaling it smaller again. This needs to be fixed in
1922 // the future.
1923 int max_width = info.width;
1924 int max_height = info.height;
1925
1926 Clip *parent = static_cast<Clip *>(ParentClip());
1927 if (parent) {
1928 if (parent->ParentTimeline()) {
1929 // Set max width/height based on parent clip's timeline (if attached to a timeline)
1930 max_width = parent->ParentTimeline()->preview_width;
1931 max_height = parent->ParentTimeline()->preview_height;
1932 }
1933 if (parent->scale == SCALE_FIT || parent->scale == SCALE_STRETCH) {
1934 // Best fit or Stretch scaling (based on max timeline size * scaling keyframes)
1935 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1936 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1937 max_width = std::max(float(max_width), max_width * max_scale_x);
1938 max_height = std::max(float(max_height), max_height * max_scale_y);
1939
1940 } else if (parent->scale == SCALE_CROP) {
1941 // Cropping scale mode (based on max timeline size * cropped size * scaling keyframes)
1942 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1943 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1944 QSize width_size(max_width * max_scale_x,
1945 round(max_width / (float(info.width) / float(info.height))));
1946 QSize height_size(round(max_height / (float(info.height) / float(info.width))),
1947 max_height * max_scale_y);
1948 // respect aspect ratio
1949 if (width_size.width() >= max_width && width_size.height() >= max_height) {
1950 max_width = std::max(max_width, width_size.width());
1951 max_height = std::max(max_height, width_size.height());
1952 } else {
1953 max_width = std::max(max_width, height_size.width());
1954 max_height = std::max(max_height, height_size.height());
1955 }
1956
1957 } else {
1958 // Scale video to equivalent unscaled size
1959 // Since the preview window can change sizes, we want to always
1960 // scale against the ratio of original video size to timeline size
1961 float preview_ratio = 1.0;
1962 if (parent->ParentTimeline()) {
1963 Timeline *t = (Timeline *) parent->ParentTimeline();
1964 preview_ratio = t->preview_width / float(t->info.width);
1965 }
1966 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1967 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1968 max_width = info.width * max_scale_x * preview_ratio;
1969 max_height = info.height * max_scale_y * preview_ratio;
1970 }
1971
1972 // If a crop effect is resizing the image, request enough pixels to preserve detail
1973 ApplyCropResizeScale(parent, info.width, info.height, max_width, max_height);
1974 }
1975
1976 if (HasMaxDecodeSize()) {
1977 QSize bounded_size(max_width, max_height);
1978 const QSize max_decode_size(MaxDecodeWidth(), MaxDecodeHeight());
1979 if (bounded_size.width() > max_decode_size.width() ||
1980 bounded_size.height() > max_decode_size.height()) {
1981 bounded_size.scale(max_decode_size, Qt::KeepAspectRatio);
1982 max_width = bounded_size.width();
1983 max_height = bounded_size.height();
1984 }
1985 }
1986
1987 // Max-size calculations above are in display-oriented coordinates. Scaling
1988 // happens before orientation is applied, so swap the decode bounds for
1989 // quarter-turn sources to preserve detail after rotation.
1990 const int quarter_turn = ((static_cast<int>(std::round(source_rotation / 90.0)) * 90) % 360 + 360) % 360;
1991 if (ApplyOrientationMetadata() && (quarter_turn == 90 || quarter_turn == 270)) {
1992 std::swap(max_width, max_height);
1993 }
1994
1995 // Determine if image needs to be scaled (for performance reasons)
1996 int original_height = src_height;
1997 if (max_width > 0 && max_height > 0 && (max_width < width || max_height < height)) {
1998 // Override width and height (but maintain aspect ratio)
1999 float ratio = float(width) / float(height);
2000 int possible_width = round(max_height * ratio);
2001 int possible_height = round(max_width / ratio);
2002
2003 if (possible_width <= max_width) {
2004 // use calculated width, and max_height
2005 width = possible_width;
2006 height = max_height;
2007 } else {
2008 // use max_width, and calculated height
2009 width = max_width;
2010 height = possible_height;
2011 }
2012 // Clip aspect ratios, animated scale/crop, and decode-size limits can
2013 // undo timeline alignment. Align the final reduced RGB dimensions here.
2014 if (src_width >= 4 && src_height >= 4) {
2015 const QSize aligned = AlignPreviewSize(QSize(width, height));
2016 width = aligned.width();
2017 height = aligned.height();
2018 }
2019 }
2020
2021 // Determine required buffer size and allocate buffer
2022 const int bytes_per_pixel = 4;
2023 int raw_buffer_size = (width * height * bytes_per_pixel) + 128;
2024
2025 // Aligned memory allocation (for speed)
2026 constexpr size_t ALIGNMENT = 32; // AVX2
2027 int buffer_size = ((raw_buffer_size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
2028 buffer = (unsigned char*) aligned_malloc(buffer_size, ALIGNMENT);
2029
2030 // Copy picture data from one AVFrame (or AVPicture) to another one.
2031 AV_COPY_PICTURE_DATA(pFrameRGB, buffer, PIX_FMT_RGBA, width, height);
2032
2033 int scale_mode = SWS_FAST_BILINEAR;
2034 if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) {
2035 scale_mode = SWS_BICUBIC;
2036 }
2037 img_convert_ctx = sws_getCachedContext(img_convert_ctx, src_width, src_height, src_pix_fmt, width, height, PIX_FMT_RGBA, scale_mode, NULL, NULL, NULL);
2038 if (!img_convert_ctx)
2039 throw OutOfMemory("Failed to initialize sws context", path);
2040 const int *src_coeff = sws_getCoefficients(SWS_CS_DEFAULT);
2041 const int *dst_coeff = sws_getCoefficients(SWS_CS_DEFAULT);
2042 const int dst_full_range = 1; // RGB outputs are full-range
2043 sws_setColorspaceDetails(img_convert_ctx, src_coeff, src_full_range ? 1 : 0,
2044 dst_coeff, dst_full_range, 0, 1 << 16, 1 << 16);
2045
2046 if (!pFrame || !pFrame->data[0] || pFrame->linesize[0] <= 0) {
2047#if USE_HW_ACCEL
2048 if (hw_de_on && hw_de_supported && !force_sw_decode) {
2049 hw_decode_failed = true;
2051 "FFmpegReader::ProcessVideoPacket (Invalid source frame; forcing software fallback)",
2052 "requested_frame", requested_frame,
2053 "current_frame", current_frame,
2054 "src_pix_fmt", src_pix_fmt,
2055 "src_width", src_width,
2056 "src_height", src_height);
2057 }
2058#endif
2059 if (pFrame) {
2060 RemoveAVFrame(pFrame);
2061 pFrame = NULL;
2062 }
2063 return;
2064 }
2065
2066 // Resize / Convert to RGB
2067 const int scaled_lines = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
2068 original_height, pFrameRGB->data, pFrameRGB->linesize);
2069 if (scaled_lines <= 0) {
2070#if USE_HW_ACCEL
2071 if (hw_de_on && hw_de_supported && !force_sw_decode) {
2072 hw_decode_failed = true;
2074 "FFmpegReader::ProcessVideoPacket (sws_scale failed; forcing software fallback)",
2075 "requested_frame", requested_frame,
2076 "current_frame", current_frame,
2077 "scaled_lines", scaled_lines,
2078 "src_pix_fmt", src_pix_fmt,
2079 "src_width", src_width,
2080 "src_height", src_height);
2081 }
2082#endif
2083 free(buffer);
2084 AV_RESET_FRAME(pFrameRGB);
2085 RemoveAVFrame(pFrame);
2086 pFrame = NULL;
2087 return;
2088 }
2089
2090 // Create or get the existing frame object
2091 std::shared_ptr<Frame> f = CreateFrame(current_frame);
2092
2093 // Add Image data to frame
2094 if (!ffmpeg_has_alpha(src_pix_fmt)) {
2095 // Add image with no alpha channel, Speed optimization
2096 f->AddImage(width, height, bytes_per_pixel, QImage::Format_RGBA8888_Premultiplied, buffer);
2097 } else {
2098 // Add image with alpha channel (this will be converted to premultipled when needed, but is slower)
2099 f->AddImage(width, height, bytes_per_pixel, QImage::Format_RGBA8888, buffer);
2100 }
2101 ApplyFrameOrientation(f);
2102 if (first_video_frame == 0 && !is_seeking) {
2103 first_video_frame = current_frame;
2104 }
2105
2106 // Update working cache
2107 working_cache.Add(f);
2108
2109 // Keep track of last last_video_frame
2110 last_video_frame = f;
2111
2112 // Free the RGB image
2113 AV_RESET_FRAME(pFrameRGB);
2114
2115 // Remove frame and packet
2116 RemoveAVFrame(pFrame);
2117
2118 // Get video PTS in seconds
2119 video_pts_seconds = (double(video_pts) * info.video_timebase.ToDouble()) + pts_offset_seconds;
2120
2121 // Debug output
2122 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (After)", "requested_frame", requested_frame, "current_frame", current_frame, "f->number", f->number, "video_pts_seconds", video_pts_seconds);
2123}
2124
2125// Process an audio packet
2126void FFmpegReader::ProcessAudioPacket(int64_t requested_frame) {
2127 AudioLocation location;
2128 // Calculate location of current audio packet
2129 if (packet && packet->pts != AV_NOPTS_VALUE) {
2130 // Determine related video frame and starting sample # from audio PTS
2131 location = GetAudioPTSLocation(packet->pts);
2132
2133 // Track 1st audio packet after a successful seek
2134 if (!seek_audio_frame_found && is_seeking)
2135 seek_audio_frame_found = location.frame;
2136 }
2137
2138 // Create or get the existing frame object. Requested frame needs to be created
2139 // in working_cache at least once. Seek can clear the working_cache, so we must
2140 // add the requested frame back to the working_cache here. If it already exists,
2141 // it will be moved to the top of the working_cache.
2142 working_cache.Add(CreateFrame(requested_frame));
2143
2144 // Debug output
2145 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Before)",
2146 "requested_frame", requested_frame,
2147 "target_frame", location.frame,
2148 "starting_sample", location.sample_start);
2149
2150 // Init an AVFrame to hold the decoded audio samples
2151 int frame_finished = 0;
2152 AVFrame *audio_frame = AV_ALLOCATE_FRAME();
2153 AV_RESET_FRAME(audio_frame);
2154
2155 int packet_samples = 0;
2156 int data_size = 0;
2157
2158#if IS_FFMPEG_3_2
2159 int send_packet_err = avcodec_send_packet(aCodecCtx, packet);
2160 if (send_packet_err < 0 && send_packet_err != AVERROR_EOF) {
2161 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Packet not sent)");
2162 }
2163 else {
2164 int receive_frame_err = avcodec_receive_frame(aCodecCtx, audio_frame);
2165 if (receive_frame_err >= 0) {
2166 frame_finished = 1;
2167 }
2168 if (receive_frame_err == AVERROR_EOF) {
2169 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (EOF detected from decoder)");
2170 packet_status.audio_eof = true;
2171 }
2172 if (receive_frame_err == AVERROR(EINVAL) || receive_frame_err == AVERROR_EOF) {
2173 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (invalid frame received or EOF from decoder)");
2174 avcodec_flush_buffers(aCodecCtx);
2175 }
2176 if (receive_frame_err != 0) {
2177 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (frame not ready yet from decoder)");
2178 }
2179 }
2180#else
2181 int used = avcodec_decode_audio4(aCodecCtx, audio_frame, &frame_finished, packet);
2182#endif
2183
2184 if (frame_finished) {
2185 packet_status.audio_decoded++;
2186
2187 // This can be different than the current packet, so we need to look
2188 // at the current AVFrame from the audio decoder. This timestamp should
2189 // be used for the remainder of this function
2190 audio_pts = audio_frame->pts;
2191
2192 // Determine related video frame and starting sample # from audio PTS
2193 location = GetAudioPTSLocation(audio_pts);
2194
2195 // determine how many samples were decoded
2196 int plane_size = -1;
2197#if HAVE_CH_LAYOUT
2198 int nb_channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout.nb_channels;
2199#else
2200 int nb_channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
2201#endif
2202 data_size = av_samples_get_buffer_size(&plane_size, nb_channels,
2203 audio_frame->nb_samples, (AVSampleFormat) (AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx)), 1);
2204
2205 // Calculate total number of samples
2206 packet_samples = audio_frame->nb_samples * nb_channels;
2207 } else {
2208 if (audio_frame) {
2209 // Free audio frame
2210 AV_FREE_FRAME(&audio_frame);
2211 }
2212 }
2213
2214 // Estimate the # of samples and the end of this packet's location (to prevent GAPS for the next timestamp)
2215 int pts_remaining_samples = packet_samples / info.channels; // Adjust for zero based array
2216
2217 // Bail if no samples found
2218 if (pts_remaining_samples == 0) {
2219 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (No samples, bailing)",
2220 "packet_samples", packet_samples,
2221 "info.channels", info.channels,
2222 "pts_remaining_samples", pts_remaining_samples);
2223 return;
2224 }
2225
2226 while (pts_remaining_samples) {
2227 // Get Samples per frame (for this frame number)
2228 int samples_per_frame = Frame::GetSamplesPerFrame(previous_packet_location.frame, info.fps, info.sample_rate, info.channels);
2229
2230 // Calculate # of samples to add to this frame
2231 int samples = samples_per_frame - previous_packet_location.sample_start;
2232 if (samples > pts_remaining_samples)
2233 samples = pts_remaining_samples;
2234
2235 // Decrement remaining samples
2236 pts_remaining_samples -= samples;
2237
2238 if (pts_remaining_samples > 0) {
2239 // next frame
2240 previous_packet_location.frame++;
2241 previous_packet_location.sample_start = 0;
2242 } else {
2243 // Increment sample start
2244 previous_packet_location.sample_start += samples;
2245 }
2246 }
2247
2248 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (ReSample)",
2249 "packet_samples", packet_samples,
2250 "info.channels", info.channels,
2251 "info.sample_rate", info.sample_rate,
2252 "aCodecCtx->sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx));
2253
2254 // Create output frame
2255 AVFrame *audio_converted = AV_ALLOCATE_FRAME();
2256 AV_RESET_FRAME(audio_converted);
2257 audio_converted->nb_samples = audio_frame->nb_samples;
2258 av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_FLTP, 0);
2259
2260 SWRCONTEXT *avr = avr_ctx;
2261 // setup resample context if needed
2262 if (!avr) {
2263 avr = SWR_ALLOC();
2264#if HAVE_CH_LAYOUT
2265 AVChannelLayout input_layout = ffmpeg_get_valid_channel_layout(
2266 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout, info.channels);
2267 AVChannelLayout output_layout = ffmpeg_get_valid_channel_layout(
2268 input_layout, info.channels);
2269 int in_layout_err = av_opt_set_chlayout(avr, "in_chlayout", &input_layout, 0);
2270 int out_layout_err = av_opt_set_chlayout(avr, "out_chlayout", &output_layout, 0);
2271#else
2272 av_opt_set_int(avr, "in_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
2273 av_opt_set_int(avr, "out_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
2274 av_opt_set_int(avr, "in_channels", info.channels, 0);
2275 av_opt_set_int(avr, "out_channels", info.channels, 0);
2276#endif
2277 av_opt_set_int(avr, "in_sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), 0);
2278 av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
2279 av_opt_set_int(avr, "in_sample_rate", info.sample_rate, 0);
2280 av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
2281 int swr_init_err = SWR_INIT(avr);
2282#if HAVE_CH_LAYOUT
2283 av_channel_layout_uninit(&input_layout);
2284 av_channel_layout_uninit(&output_layout);
2285 if (in_layout_err < 0 || out_layout_err < 0 || swr_init_err < 0) {
2286 SWR_FREE(&avr);
2287 throw InvalidChannels("Could not initialize FFmpeg audio channel layout or resampler.", path);
2288 }
2289#else
2290 if (swr_init_err < 0) {
2291 SWR_FREE(&avr);
2292 throw InvalidChannels("Could not initialize FFmpeg audio resampler.", path);
2293 }
2294#endif
2295 avr_ctx = avr;
2296 }
2297
2298 // Convert audio samples
2299 int nb_samples = SWR_CONVERT(avr, // audio resample context
2300 audio_converted->data, // output data pointers
2301 audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
2302 audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
2303 audio_frame->data, // input data pointers
2304 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
2305 audio_frame->nb_samples); // number of input samples to convert
2306
2307
2308 int64_t starting_frame_number = -1;
2309 for (int channel_filter = 0; channel_filter < info.channels; channel_filter++) {
2310 // Array of floats (to hold samples for each channel)
2311 starting_frame_number = location.frame;
2312 int channel_buffer_size = nb_samples;
2313 auto *channel_buffer = (float *) (audio_converted->data[channel_filter]);
2314
2315 // Loop through samples, and add them to the correct frames
2316 int start = location.sample_start;
2317 int remaining_samples = channel_buffer_size;
2318 while (remaining_samples > 0) {
2319 // Get Samples per frame (for this frame number)
2320 int samples_per_frame = Frame::GetSamplesPerFrame(starting_frame_number, info.fps, info.sample_rate, info.channels);
2321
2322 // Calculate # of samples to add to this frame
2323 int samples = std::fmin(samples_per_frame - start, remaining_samples);
2324
2325 // Create or get the existing frame object
2326 std::shared_ptr<Frame> f = CreateFrame(starting_frame_number);
2327
2328 // Add samples for current channel to the frame.
2329 f->AddAudio(true, channel_filter, start, channel_buffer, samples, 1.0f);
2330
2331 // Debug output
2332 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (f->AddAudio)",
2333 "frame", starting_frame_number,
2334 "start", start,
2335 "samples", samples,
2336 "channel", channel_filter,
2337 "samples_per_frame", samples_per_frame);
2338
2339 // Add or update cache
2340 working_cache.Add(f);
2341
2342 // Decrement remaining samples
2343 remaining_samples -= samples;
2344
2345 // Increment buffer (to next set of samples)
2346 if (remaining_samples > 0)
2347 channel_buffer += samples;
2348
2349 // Increment frame number
2350 starting_frame_number++;
2351
2352 // Reset starting sample #
2353 start = 0;
2354 }
2355 }
2356
2357 // Free AVFrames
2358 av_free(audio_converted->data[0]);
2359 AV_FREE_FRAME(&audio_converted);
2360 AV_FREE_FRAME(&audio_frame);
2361
2362 // Get audio PTS in seconds
2363 audio_pts_seconds = (double(audio_pts) * info.audio_timebase.ToDouble()) + pts_offset_seconds;
2364
2365 // Debug output
2366 Logger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (After)",
2367 "requested_frame", requested_frame,
2368 "starting_frame", location.frame,
2369 "end_frame", starting_frame_number - 1,
2370 "audio_pts_seconds", audio_pts_seconds);
2371
2372}
2373
2374
2375// Seek to a specific frame. This is not always frame accurate, it's more of an estimation on many codecs.
2376void FFmpegReader::Seek(int64_t requested_frame) {
2377 // Adjust for a requested frame that is too small or too large
2378 if (requested_frame < 1)
2379 requested_frame = 1;
2380 if (requested_frame > info.video_length)
2381 requested_frame = info.video_length;
2382 if (requested_frame > largest_frame_processed && packet_status.end_of_file) {
2383 // Not possible to search past largest_frame once EOF is reached (no more packets)
2384 return;
2385 }
2386
2387 // Debug output
2388 Logger::Instance()->AppendDebugMethod("FFmpegReader::Seek",
2389 "requested_frame", requested_frame,
2390 "seek_count", seek_count,
2391 "last_frame", last_frame);
2392
2393 // Clear working cache (since we are seeking to another location in the file)
2394 working_cache.Clear();
2395
2396 // Reset the last frame variable
2397 video_pts = 0.0;
2398 video_pts_seconds = NO_PTS_OFFSET;
2399 audio_pts = 0.0;
2400 audio_pts_seconds = NO_PTS_OFFSET;
2401 hold_packet = false;
2402 last_frame = 0;
2403 current_video_frame = 0;
2404 // A seek landing is not the beginning. Close/Open below resets this for a restart.
2405 first_video_frame = -1;
2406 largest_frame_processed = 0;
2407 last_final_video_frame.reset();
2408 bool has_audio_override = info.has_audio;
2409 bool has_video_override = info.has_video;
2410
2411 // Init end-of-file detection variables
2412 packet_status.reset(false);
2413
2414 // Increment seek count
2415 seek_count++;
2416
2417 // If seeking near frame 1, we need to close and re-open the file (this is more reliable than seeking)
2418 int buffer_amount = 12;
2419 if (requested_frame - buffer_amount < 20) {
2420 // prevent Open() from seeking again
2421 is_seeking = true;
2422
2423 // Close and re-open file (basically seeking to frame 1)
2424 Close();
2425 Open();
2426
2427 // Update overrides (since closing and re-opening might update these)
2428 info.has_audio = has_audio_override;
2429 info.has_video = has_video_override;
2430
2431 // Not actually seeking, so clear these flags
2432 is_seeking = false;
2433 if (seek_count == 1) {
2434 // Don't redefine this on multiple seek attempts for a specific frame
2435 seeking_frame = 1;
2436 seeking_pts = ConvertFrameToVideoPTS(1);
2437 }
2438 seek_audio_frame_found = 0; // used to detect which frames to throw away after a seek
2439 seek_video_frame_found = 0; // used to detect which frames to throw away after a seek
2440
2441 } else {
2442 // Seek to nearest key-frame (aka, i-frame)
2443 bool seek_worked = false;
2444 int64_t seek_target = 0;
2445
2446 // Seek video stream (if any), except album arts
2447 if (!seek_worked && info.has_video && !HasAlbumArt()) {
2448 seek_target = ConvertFrameToVideoPTS(requested_frame - buffer_amount);
2449 if (av_seek_frame(pFormatCtx, info.video_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) {
2450 Logger::Instance()->Log(std::string(pFormatCtx->AV_FILENAME) + ": error while seeking video stream");
2451 } else {
2452 // VIDEO SEEK
2453 is_video_seek = true;
2454 seek_worked = true;
2455 }
2456 }
2457
2458 // Seek audio stream (if not already seeked... and if an audio stream is found)
2459 if (!seek_worked && info.has_audio) {
2460 seek_target = ConvertFrameToAudioPTS(requested_frame - buffer_amount);
2461 if (av_seek_frame(pFormatCtx, info.audio_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) {
2462 Logger::Instance()->Log(std::string(pFormatCtx->AV_FILENAME) + ": error while seeking audio stream");
2463 } else {
2464 // AUDIO SEEK
2465 is_video_seek = false;
2466 seek_worked = true;
2467 }
2468 }
2469
2470 // Was the seek successful?
2471 if (seek_worked) {
2472 // Flush audio buffer
2473 if (info.has_audio)
2474 avcodec_flush_buffers(aCodecCtx);
2475
2476 // Flush video buffer
2477 if (info.has_video)
2478 avcodec_flush_buffers(pCodecCtx);
2479
2480 // Reset previous audio location to zero
2481 previous_packet_location.frame = -1;
2482 previous_packet_location.sample_start = 0;
2483
2484 // init seek flags
2485 is_seeking = true;
2486 if (seek_count == 1) {
2487 // Don't redefine this on multiple seek attempts for a specific frame
2488 seeking_pts = seek_target;
2489 seeking_frame = requested_frame;
2490 }
2491 seek_audio_frame_found = 0; // used to detect which frames to throw away after a seek
2492 seek_video_frame_found = 0; // used to detect which frames to throw away after a seek
2493
2494 } else {
2495 // seek failed
2496 seeking_pts = 0;
2497 seeking_frame = 0;
2498
2499 // prevent Open() from seeking again
2500 is_seeking = true;
2501
2502 // Close and re-open file (basically seeking to frame 1)
2503 Close();
2504 Open();
2505
2506 // Not actually seeking, so clear these flags
2507 is_seeking = false;
2508
2509 // disable seeking for this reader (since it failed)
2510 enable_seek = false;
2511
2512 // Update overrides (since closing and re-opening might update these)
2513 info.has_audio = has_audio_override;
2514 info.has_video = has_video_override;
2515 }
2516 }
2517}
2518
2519// Get the PTS for the current video packet
2520int64_t FFmpegReader::GetPacketPTS() {
2521 if (packet) {
2522 int64_t current_pts = packet->pts;
2523 if (current_pts == AV_NOPTS_VALUE && packet->dts != AV_NOPTS_VALUE)
2524 current_pts = packet->dts;
2525
2526 // Return adjusted PTS
2527 return current_pts;
2528 } else {
2529 // No packet, return NO PTS
2530 return AV_NOPTS_VALUE;
2531 }
2532}
2533
2534// Update PTS Offset (if any)
2535void FFmpegReader::UpdatePTSOffset() {
2536 if (pts_offset_seconds != NO_PTS_OFFSET) {
2537 // Skip this method if we have already set PTS offset
2538 return;
2539 }
2540 pts_offset_seconds = 0.0;
2541 double video_pts_offset_seconds = 0.0;
2542 double audio_pts_offset_seconds = 0.0;
2543
2544 bool has_video_pts = false;
2545 if (!info.has_video) {
2546 // Mark as checked
2547 has_video_pts = true;
2548 }
2549 bool has_audio_pts = false;
2550 if (!info.has_audio) {
2551 // Mark as checked
2552 has_audio_pts = true;
2553 }
2554
2555 // Loop through the stream (until a packet from all streams is found)
2556 while (!has_video_pts || !has_audio_pts) {
2557 // Get the next packet (if any)
2558 if (GetNextPacket() < 0)
2559 // Break loop when no more packets found
2560 break;
2561
2562 // Get PTS of this packet
2563 int64_t pts = GetPacketPTS();
2564
2565 // Video packet
2566 if (!has_video_pts && packet->stream_index == videoStream) {
2567 // Get the video packet start time (in seconds)
2568 video_pts_offset_seconds = 0.0 - (pts * info.video_timebase.ToDouble());
2569
2570 // Is timestamp close to zero (within X seconds)
2571 // Ignore wildly invalid timestamps (i.e. -234923423423)
2572 if (std::abs(video_pts_offset_seconds) <= 10.0) {
2573 has_video_pts = true;
2574 }
2575 }
2576 else if (!has_audio_pts && packet->stream_index == audioStream) {
2577 // Get the audio packet start time (in seconds)
2578 audio_pts_offset_seconds = 0.0 - (pts * info.audio_timebase.ToDouble());
2579
2580 // Is timestamp close to zero (within X seconds)
2581 // Ignore wildly invalid timestamps (i.e. -234923423423)
2582 if (std::abs(audio_pts_offset_seconds) <= 10.0) {
2583 has_audio_pts = true;
2584 }
2585 }
2586 }
2587
2588 // Choose timestamp origin:
2589 // - If video exists, anchor timeline frame mapping to video start.
2590 // This avoids AAC priming / audio preroll shifting video frame 1 to frame 2.
2591 // - If no video exists (audio-only readers), use audio start.
2592 if (info.has_video && has_video_pts) {
2593 pts_offset_seconds = video_pts_offset_seconds;
2594 } else if (!info.has_video && has_audio_pts) {
2595 pts_offset_seconds = audio_pts_offset_seconds;
2596 } else if (has_video_pts && has_audio_pts) {
2597 // Fallback when stream flags are unusual but both timestamps exist.
2598 pts_offset_seconds = video_pts_offset_seconds;
2599 }
2600}
2601
2602// Convert PTS into Frame Number
2603int64_t FFmpegReader::ConvertVideoPTStoFrame(int64_t pts) {
2604 // Apply PTS offset
2605 int64_t previous_video_frame = current_video_frame;
2606 const double fps_value = (info.fps.num > 0 && info.fps.den > 0) ? info.fps.ToDouble() : 30.0;
2607 const double video_timebase_value =
2610 : (1.0 / 30.0);
2611
2612 // Get the video packet start time (in seconds)
2613 double video_seconds = (double(pts) * video_timebase_value) + pts_offset_seconds;
2614
2615 // Divide by the video timebase, to get the video frame number (frame # is decimal at this point)
2616 int64_t frame = round(video_seconds * fps_value) + 1;
2617
2618 // Keep track of the expected video frame #
2619 if (current_video_frame == 0)
2620 current_video_frame = frame;
2621 else {
2622
2623 // Sometimes frames are duplicated due to identical (or similar) timestamps
2624 if (frame == previous_video_frame) {
2625 // return -1 frame number
2626 frame = -1;
2627 } else {
2628 // Increment expected frame
2629 current_video_frame++;
2630 }
2631 }
2632
2633 // Return frame #
2634 return frame;
2635}
2636
2637// Convert Frame Number into Video PTS
2638int64_t FFmpegReader::ConvertFrameToVideoPTS(int64_t frame_number) {
2639 const double fps_value = (info.fps.num > 0 && info.fps.den > 0) ? info.fps.ToDouble() : 30.0;
2640 const double video_timebase_value =
2643 : (1.0 / 30.0);
2644
2645 // Get timestamp of this frame (in seconds)
2646 double seconds = (double(frame_number - 1) / fps_value) + pts_offset_seconds;
2647
2648 // Calculate the # of video packets in this timestamp
2649 int64_t video_pts = round(seconds / video_timebase_value);
2650
2651 // Apply PTS offset (opposite)
2652 return video_pts;
2653}
2654
2655// Convert Frame Number into Video PTS
2656int64_t FFmpegReader::ConvertFrameToAudioPTS(int64_t frame_number) {
2657 const double fps_value = (info.fps.num > 0 && info.fps.den > 0) ? info.fps.ToDouble() : 30.0;
2658 const double audio_timebase_value =
2661 : (1.0 / 48000.0);
2662
2663 // Get timestamp of this frame (in seconds)
2664 double seconds = (double(frame_number - 1) / fps_value) + pts_offset_seconds;
2665
2666 // Calculate the # of audio packets in this timestamp
2667 int64_t audio_pts = round(seconds / audio_timebase_value);
2668
2669 // Apply PTS offset (opposite)
2670 return audio_pts;
2671}
2672
2673// Calculate Starting video frame and sample # for an audio PTS
2674AudioLocation FFmpegReader::GetAudioPTSLocation(int64_t pts) {
2675 const double audio_timebase_value =
2678 : (1.0 / 48000.0);
2679 const double fps_value = (info.fps.num > 0 && info.fps.den > 0) ? info.fps.ToDouble() : 30.0;
2680
2681 // Get the audio packet start time (in seconds)
2682 double audio_seconds = (double(pts) * audio_timebase_value) + pts_offset_seconds;
2683
2684 // Divide by the video timebase, to get the video frame number (frame # is decimal at this point)
2685 double frame = (audio_seconds * fps_value) + 1;
2686
2687 // Frame # as a whole number (no more decimals)
2688 int64_t whole_frame = int64_t(frame);
2689
2690 // Remove the whole number, and only get the decimal of the frame
2691 double sample_start_percentage = frame - double(whole_frame);
2692
2693 // Get Samples per frame
2694 int samples_per_frame = Frame::GetSamplesPerFrame(whole_frame, info.fps, info.sample_rate, info.channels);
2695
2696 // Calculate the sample # to start on
2697 int sample_start = round(double(samples_per_frame) * sample_start_percentage);
2698
2699 // Protect against broken (i.e. negative) timestamps
2700 if (whole_frame < 1)
2701 whole_frame = 1;
2702 if (sample_start < 0)
2703 sample_start = 0;
2704
2705 // Prepare final audio packet location
2706 AudioLocation location = {whole_frame, sample_start};
2707
2708 // Compare to previous audio packet (and fix small gaps due to varying PTS timestamps)
2709 if (previous_packet_location.frame != -1) {
2710 if (location.is_near(previous_packet_location, samples_per_frame, samples_per_frame)) {
2711 int64_t orig_frame = location.frame;
2712 int orig_start = location.sample_start;
2713
2714 // Update sample start, to prevent gaps in audio
2715 location.sample_start = previous_packet_location.sample_start;
2716 location.frame = previous_packet_location.frame;
2717
2718 // Debug output
2719 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAudioPTSLocation (Audio Gap Detected)", "Source Frame", orig_frame, "Source Audio Sample", orig_start, "Target Frame", location.frame, "Target Audio Sample", location.sample_start, "pts", pts);
2720
2721 } else {
2722 // Debug output
2723 Logger::Instance()->AppendDebugMethod("FFmpegReader::GetAudioPTSLocation (Audio Gap Ignored - too big)", "Previous location frame", previous_packet_location.frame, "Target Frame", location.frame, "Target Audio Sample", location.sample_start, "pts", pts);
2724 }
2725 }
2726
2727 // Set previous location
2728 previous_packet_location = location;
2729
2730 // Return the associated video frame and starting sample #
2731 return location;
2732}
2733
2734// Create a new Frame (or return an existing one) and add it to the working queue.
2735std::shared_ptr<Frame> FFmpegReader::CreateFrame(int64_t requested_frame) {
2736 // Check working cache
2737 std::shared_ptr<Frame> output = working_cache.GetFrame(requested_frame);
2738
2739 if (!output) {
2740 // (re-)Check working cache
2741 output = working_cache.GetFrame(requested_frame);
2742 if(output) return output;
2743
2744 // Create a new frame on the working cache
2745 output = std::make_shared<Frame>(requested_frame, info.width, info.height, "#000000", Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels), info.channels);
2746 output->SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den); // update pixel ratio
2747 output->ChannelsLayout(info.channel_layout); // update audio channel layout from the parent reader
2748 output->SampleRate(info.sample_rate); // update the frame's sample rate of the parent reader
2749
2750 working_cache.Add(output);
2751
2752 // Set the largest processed frame (if this is larger)
2753 if (requested_frame > largest_frame_processed)
2754 largest_frame_processed = requested_frame;
2755 }
2756 // Return frame
2757 return output;
2758}
2759
2760// Determine if frame is partial due to seek
2761bool FFmpegReader::IsPartialFrame(int64_t requested_frame) {
2762
2763 // Sometimes a seek gets partial frames, and we need to remove them
2764 bool seek_trash = false;
2765 int64_t max_seeked_frame = seek_audio_frame_found; // determine max seeked frame
2766 if (seek_video_frame_found > max_seeked_frame) {
2767 max_seeked_frame = seek_video_frame_found;
2768 }
2769 if ((info.has_audio && seek_audio_frame_found && max_seeked_frame >= requested_frame) ||
2770 (info.has_video && seek_video_frame_found && max_seeked_frame >= requested_frame)) {
2771 seek_trash = true;
2772 }
2773
2774 return seek_trash;
2775}
2776
2777// Check the working queue, and move finished frames to the finished queue
2778void FFmpegReader::CheckWorkingFrames(int64_t requested_frame) {
2779
2780 // Prevent async calls to the following code
2781 const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
2782
2783 // Get a list of current working queue frames in the cache (in-progress frames)
2784 std::vector<std::shared_ptr<openshot::Frame>> working_frames = working_cache.GetFrames();
2785 std::vector<std::shared_ptr<openshot::Frame>>::iterator working_itr;
2786
2787 // Loop through all working queue frames (sorted by frame #)
2788 for(working_itr = working_frames.begin(); working_itr != working_frames.end(); ++working_itr)
2789 {
2790 // Get working frame
2791 std::shared_ptr<Frame> f = *working_itr;
2792
2793 // Was a frame found? Is frame requested yet?
2794 if (!f || f->number > requested_frame) {
2795 // If not, skip to next one
2796 continue;
2797 }
2798
2799 // Calculate PTS in seconds (of working frame), and the most recent processed pts value
2800 double frame_pts_seconds = (double(f->number - 1) / info.fps.ToDouble()) + pts_offset_seconds;
2801 double recent_pts_seconds = std::max(video_pts_seconds, audio_pts_seconds);
2802
2803 // Determine if video and audio are ready (based on timestamps)
2804 bool is_video_ready = false;
2805 bool is_audio_ready = false;
2806 double recent_pts_diff = recent_pts_seconds - frame_pts_seconds;
2807 if ((frame_pts_seconds <= video_pts_seconds)
2808 || (recent_pts_diff > 1.5)
2809 || packet_status.video_eof || packet_status.end_of_file) {
2810 // Video stream is past this frame (so it must be done)
2811 // OR video stream is too far behind, missing, or end-of-file
2812 is_video_ready = true;
2813 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (video ready)",
2814 "frame_number", f->number,
2815 "frame_pts_seconds", frame_pts_seconds,
2816 "video_pts_seconds", video_pts_seconds,
2817 "recent_pts_diff", recent_pts_diff);
2818 if (info.has_video && !f->has_image_data &&
2819 (packet_status.video_eof || packet_status.end_of_file)) {
2820 // Frame has no image data. Prefer timeline-previous frames to preserve
2821 // visual order, especially when decode/prefetch is out-of-order.
2822 std::shared_ptr<Frame> previous_frame_instance = final_cache.GetFrame(f->number - 1);
2823 if (previous_frame_instance && previous_frame_instance->has_image_data) {
2824 f->AddImage(std::make_shared<QImage>(previous_frame_instance->GetImage()->copy()));
2825 }
2826
2827 // Fall back to last finalized timeline image (survives cache churn).
2828 if (!f->has_image_data
2829 && last_final_video_frame
2830 && last_final_video_frame->has_image_data
2831 && last_final_video_frame->number <= f->number) {
2832 f->AddImage(std::make_shared<QImage>(last_final_video_frame->GetImage()->copy()));
2833 }
2834
2835 // Fall back to the last decoded image only when it is not from the future.
2836 if (!f->has_image_data
2837 && last_video_frame
2838 && last_video_frame->has_image_data
2839 && last_video_frame->number <= f->number) {
2840 f->AddImage(std::make_shared<QImage>(last_video_frame->GetImage()->copy()));
2841 }
2842
2843 // Last-resort fallback if no prior image is available.
2844 if (!f->has_image_data) {
2846 "FFmpegReader::CheckWorkingFrames (no previous image found; using black frame)",
2847 "frame_number", f->number);
2848 f->AddColor("#000000");
2849 }
2850 }
2851 }
2852
2853 double audio_pts_diff = audio_pts_seconds - frame_pts_seconds;
2854 if ((frame_pts_seconds < audio_pts_seconds && audio_pts_diff > 1.0)
2855 || (recent_pts_diff > 1.5)
2856 || packet_status.audio_eof || packet_status.end_of_file) {
2857 // Audio stream is past this frame (so it must be done)
2858 // OR audio stream is too far behind, missing, or end-of-file
2859 // Adding a bit of margin here, to allow for partial audio packets
2860 is_audio_ready = true;
2861 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (audio ready)",
2862 "frame_number", f->number,
2863 "frame_pts_seconds", frame_pts_seconds,
2864 "audio_pts_seconds", audio_pts_seconds,
2865 "audio_pts_diff", audio_pts_diff,
2866 "recent_pts_diff", recent_pts_diff);
2867 }
2868 bool is_seek_trash = IsPartialFrame(f->number);
2869
2870 // Adjust for available streams
2871 if (!info.has_video) is_video_ready = true;
2872 if (!info.has_audio) is_audio_ready = true;
2873
2874 // Debug output
2875 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames",
2876 "frame_number", f->number,
2877 "is_video_ready", is_video_ready,
2878 "is_audio_ready", is_audio_ready,
2879 "video_eof", packet_status.video_eof,
2880 "audio_eof", packet_status.audio_eof,
2881 "end_of_file", packet_status.end_of_file);
2882
2883 // Check if working frame is final
2884 if (info.has_video && !f->has_image_data
2885 && !packet_status.end_of_file && !is_seek_trash) {
2886 if (info.has_single_image) {
2887 // For still-image video (including attached cover art), reuse the most
2888 // recent image so playback does not stall waiting for video EOF.
2889 std::shared_ptr<Frame> previous_frame_instance = final_cache.GetFrame(f->number - 1);
2890 if (previous_frame_instance && previous_frame_instance->has_image_data) {
2891 f->AddImage(std::make_shared<QImage>(previous_frame_instance->GetImage()->copy()));
2892 }
2893 if (!f->has_image_data
2894 && last_final_video_frame
2895 && last_final_video_frame->has_image_data
2896 && last_final_video_frame->number <= f->number) {
2897 f->AddImage(std::make_shared<QImage>(last_final_video_frame->GetImage()->copy()));
2898 }
2899 if (!f->has_image_data
2900 && last_video_frame
2901 && last_video_frame->has_image_data
2902 && last_video_frame->number <= f->number) {
2903 f->AddImage(std::make_shared<QImage>(last_video_frame->GetImage()->copy()));
2904 }
2905 }
2906
2907 // If both streams have advanced past this frame but the decoder never
2908 // produced image data for it, reuse the most recent non-future image.
2909 // This avoids stalling indefinitely on sparse/missing decoded frames.
2910 if (!f->has_image_data && is_video_ready && is_audio_ready) {
2911 std::shared_ptr<Frame> previous_frame_instance = final_cache.GetFrame(f->number - 1);
2912 if (previous_frame_instance && previous_frame_instance->has_image_data) {
2913 f->AddImage(std::make_shared<QImage>(previous_frame_instance->GetImage()->copy()));
2914 }
2915 if (!f->has_image_data
2916 && last_final_video_frame
2917 && last_final_video_frame->has_image_data
2918 && last_final_video_frame->number <= f->number) {
2919 f->AddImage(std::make_shared<QImage>(last_final_video_frame->GetImage()->copy()));
2920 }
2921 if (!f->has_image_data
2922 && last_video_frame
2923 && last_video_frame->has_image_data
2924 && last_video_frame->number <= f->number) {
2925 f->AddImage(std::make_shared<QImage>(last_video_frame->GetImage()->copy()));
2926 }
2927 }
2928
2929 // A decoded picture from the start establishes the initial gap. Fill only
2930 // that gap, after the normal audio readiness check, rather than reading
2931 // to EOF waiting for an image that cannot arrive. Do not use seek landings.
2932 if (!f->has_image_data && is_video_ready && is_audio_ready
2933 && !is_seeking && first_video_frame > f->number) {
2934 f->AddColor("#000000");
2935 }
2936
2937 // Do not finalize non-EOF video frames without decoded image data.
2938 // This prevents repeated previous-frame fallbacks being cached as real frames.
2939 if (!f->has_image_data) {
2940 continue;
2941 }
2942 }
2943 if ((!packet_status.end_of_file && is_video_ready && is_audio_ready) || packet_status.end_of_file || is_seek_trash) {
2944 // Debug output
2945 Logger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (mark frame as final)",
2946 "requested_frame", requested_frame,
2947 "f->number", f->number,
2948 "is_seek_trash", is_seek_trash,
2949 "Working Cache Count", working_cache.Count(),
2950 "Final Cache Count", final_cache.Count(),
2951 "end_of_file", packet_status.end_of_file);
2952
2953 if (!is_seek_trash) {
2954 // Move frame to final cache
2955 final_cache.Add(f);
2956 if (f->has_image_data) {
2957 last_final_video_frame = f;
2958 }
2959
2960 // Remove frame from working cache
2961 working_cache.Remove(f->number);
2962
2963 // Update last frame processed
2964 last_frame = f->number;
2965 } else {
2966 // Seek trash, so delete the frame from the working cache, and never add it to the final cache.
2967 working_cache.Remove(f->number);
2968 }
2969
2970 }
2971 }
2972
2973 // Clear vector of frames
2974 working_frames.clear();
2975 working_frames.shrink_to_fit();
2976}
2977
2978// Check for the correct frames per second (FPS) value by scanning the 1st few seconds of video packets.
2979void FFmpegReader::CheckFPS() {
2980 if (check_fps) {
2981 // Do not check FPS more than 1 time
2982 return;
2983 } else {
2984 check_fps = true;
2985 }
2986
2987 int frames_per_second[3] = {0,0,0};
2988 int max_fps_index = sizeof(frames_per_second) / sizeof(frames_per_second[0]);
2989 int fps_index = 0;
2990
2991 int all_frames_detected = 0;
2992 int starting_frames_detected = 0;
2993
2994 // Loop through the stream
2995 while (true) {
2996 // Get the next packet (if any)
2997 if (GetNextPacket() < 0)
2998 // Break loop when no more packets found
2999 break;
3000
3001 // Video packet
3002 if (packet->stream_index == videoStream) {
3003 // Get the video packet start time (in seconds)
3004 double video_seconds = (double(GetPacketPTS()) * info.video_timebase.ToDouble()) + pts_offset_seconds;
3005 fps_index = int(video_seconds); // truncate float timestamp to int (second 1, second 2, second 3)
3006
3007 // Is this video packet from the first few seconds?
3008 if (fps_index >= 0 && fps_index < max_fps_index) {
3009 // Yes, keep track of how many frames per second (over the first few seconds)
3010 starting_frames_detected++;
3011 frames_per_second[fps_index]++;
3012 }
3013
3014 // Track all video packets detected
3015 all_frames_detected++;
3016 }
3017 }
3018
3019 // Calculate FPS (based on the first few seconds of video packets)
3020 float avg_fps = 30.0;
3021 if (starting_frames_detected > 0 && fps_index > 0) {
3022 avg_fps = float(starting_frames_detected) / std::min(fps_index, max_fps_index);
3023 }
3024
3025 // Verify average FPS is a reasonable value
3026 if (avg_fps < 8.0) {
3027 // Invalid FPS assumed, so switching to a sane default FPS instead
3028 avg_fps = 30.0;
3029 }
3030
3031 // Update FPS (truncate average FPS to Integer)
3032 info.fps = Fraction(int(avg_fps), 1);
3033
3034 // Update Duration and Length
3035 if (all_frames_detected > 0) {
3036 // Use all video frames detected to calculate # of frames
3037 info.video_length = all_frames_detected;
3038 info.duration = all_frames_detected / avg_fps;
3039 } else {
3040 // Use previous duration to calculate # of frames
3041 info.video_length = info.duration * avg_fps;
3042 }
3043
3044 // Update video bit rate
3046}
3047
3048// Remove AVFrame from cache (and deallocate its memory)
3049void FFmpegReader::RemoveAVFrame(AVFrame *remove_frame) {
3050 // Remove pFrame (if exists)
3051 if (remove_frame) {
3052 // Free memory
3053 av_freep(&remove_frame->data[0]);
3054#ifndef WIN32
3055 AV_FREE_FRAME(&remove_frame);
3056#endif
3057 }
3058}
3059
3060// Remove AVPacket from cache (and deallocate its memory)
3061void FFmpegReader::RemoveAVPacket(AVPacket *remove_packet) {
3062 // deallocate memory for packet
3063 AV_FREE_PACKET(remove_packet);
3064
3065 // Delete the object
3066 delete remove_packet;
3067}
3068
3069// Generate JSON string of this object
3070std::string FFmpegReader::Json() const {
3071
3072 // Return formatted string
3073 return JsonValue().toStyledString();
3074}
3075
3076// Generate Json::Value for this object
3077Json::Value FFmpegReader::JsonValue() const {
3078
3079 // Create root json object
3080 Json::Value root = ReaderBase::JsonValue(); // get parent properties
3081 root["type"] = "FFmpegReader";
3082 root["path"] = path;
3083 switch (duration_strategy) {
3085 root["duration_strategy"] = "VideoPreferred";
3086 break;
3088 root["duration_strategy"] = "AudioPreferred";
3089 break;
3091 default:
3092 root["duration_strategy"] = "LongestStream";
3093 break;
3094 }
3095
3096 // return JsonValue
3097 return root;
3098}
3099
3100// Load JSON string into this object
3101void FFmpegReader::SetJson(const std::string value) {
3102
3103 // Parse JSON string into JSON objects
3104 try {
3105 const Json::Value root = openshot::stringToJson(value);
3106 // Set all values that match
3107 SetJsonValue(root);
3108 }
3109 catch (const std::exception& e) {
3110 // Error parsing JSON (or missing keys)
3111 throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
3112 }
3113}
3114
3115// Load Json::Value into this object
3116void FFmpegReader::SetJsonValue(const Json::Value root) {
3117
3118 // Set parent data
3120
3121 // Set data from Json (if key is found)
3122 if (!root["path"].isNull())
3123 path = root["path"].asString();
3124 if (!root["duration_strategy"].isNull()) {
3125 const std::string strategy = root["duration_strategy"].asString();
3126 if (strategy == "VideoPreferred") {
3127 duration_strategy = DurationStrategy::VideoPreferred;
3128 } else if (strategy == "AudioPreferred") {
3129 duration_strategy = DurationStrategy::AudioPreferred;
3130 } else {
3131 duration_strategy = DurationStrategy::LongestStream;
3132 }
3133 }
3134}
Shared helpers for Crop effect scaling logic.
Header file for all Exception classes.
AVPixelFormat NormalizeDeprecatedPixFmt(AVPixelFormat pix_fmt, bool &is_full_range)
AVPixelFormat hw_de_av_pix_fmt_global
AVHWDeviceType hw_de_av_device_type_global
int hw_de_on
Header file for FFmpegReader class.
Header file for FFmpegUtilities.
#define AV_FREE_CONTEXT(av_context)
#define SWR_INIT(ctx)
#define AV_FREE_FRAME(av_frame)
#define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count)
#define SWR_ALLOC()
#define SWR_CLOSE(ctx)
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
#define AV_GET_CODEC_CONTEXT(av_stream, av_codec)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
#define AV_ALLOCATE_FRAME()
#define AV_REGISTER_ALL
#define PIX_FMT_RGBA
#define SWR_FREE(ctx)
#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height)
#define AV_FREE_PACKET(av_packet)
#define SWRCONTEXT
#define AVCODEC_REGISTER_ALL
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height)
#define AV_GET_SAMPLE_FORMAT(av_stream, av_context)
#define AV_RESET_FRAME(av_frame)
AVDictionary * opts
if(!codec) codec
Cross-platform helper to encourage returning freed memory to the OS.
#define FF_VIDEO_NUM_PROCESSORS
#define OPEN_MP_NUM_PROCESSORS
#define FF_AUDIO_NUM_PROCESSORS
Header file for Timeline class.
void SetMaxBytesFromInfo(int64_t number_of_frames, int width, int height, int sample_rate, int channels)
Set maximum bytes to a different amount based on a ReaderInfo struct.
Definition: CacheBase.cpp:28
int64_t Count()
Count the frames in the queue.
void Add(std::shared_ptr< openshot::Frame > frame)
Add a Frame to the cache.
Definition: CacheMemory.cpp:47
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number)
Get a frame from the cache.
Definition: CacheMemory.cpp:84
std::vector< std::shared_ptr< openshot::Frame > > GetFrames()
Get an array of all Frames.
void Remove(int64_t frame_number)
Remove a specific frame.
void Clear()
Clear the cache of all frames.
This class represents a clip (used to arrange readers on the timeline)
Definition: Clip.h:89
openshot::Keyframe scale_x
Curve representing the horizontal scaling in percent (0 to 1)
Definition: Clip.h:334
openshot::TimelineBase * ParentTimeline() override
Get the associated Timeline pointer (if any)
Definition: Clip.h:310
openshot::Keyframe scale_y
Curve representing the vertical scaling in percent (0 to 1)
Definition: Clip.h:335
openshot::ScaleType scale
Definition: Clip.h:186
double Y
The Y value of the coordinate (usually representing the value of the property being animated)
Definition: Coordinate.h:41
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
Definition: FFmpegReader.h:103
void Open() override
Open File - which is called by the constructor automatically.
bool HardwareDecodeSuccessful() const override
Return true if hardware decode was requested and successfully produced at least one frame.
FFmpegReader(const std::string &path, bool inspect_reader=true)
Constructor for FFmpegReader.
Json::Value JsonValue() const override
Generate Json::Value for this object.
bool GetIsDurationKnown()
Return true if frame can be read with GetFrame()
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
CacheMemory final_cache
Final cache object used to hold final frames.
Definition: FFmpegReader.h:268
virtual ~FFmpegReader()
Destructor.
std::string Json() const override
Generate JSON string of this object.
std::shared_ptr< openshot::Frame > GetFrame(int64_t requested_frame) override
void Close() override
Close File.
void SetJson(const std::string value) override
Load JSON string into this object.
This class represents a fraction.
Definition: Fraction.h:30
int num
Numerator for the fraction.
Definition: Fraction.h:32
float ToFloat()
Return this fraction as a float (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:35
double ToDouble() const
Return this fraction as a double (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:40
Fraction Reciprocal() const
Return the reciprocal as a Fraction.
Definition: Fraction.cpp:78
int den
Denominator for the fraction.
Definition: Fraction.h:33
int GetSamplesPerFrame(openshot::Fraction fps, int sample_rate, int channels)
Calculate the # of samples per video frame (for the current frame number)
Definition: Frame.cpp:486
Exception when an invalid # of audio channels are detected.
Definition: Exceptions.h:164
Exception when no valid codec is found for a file.
Definition: Exceptions.h:179
Exception for files that can not be found or opened.
Definition: Exceptions.h:194
Exception for invalid JSON.
Definition: Exceptions.h:224
Point GetMaxPoint() const
Get max point (by Y coordinate)
Definition: KeyFrame.cpp:245
void AppendDebugMethod(std::string method_name, std::string arg1_name="", float arg1_value=-1.0, std::string arg2_name="", float arg2_value=-1.0, std::string arg3_name="", float arg3_value=-1.0, std::string arg4_name="", float arg4_value=-1.0, std::string arg5_name="", float arg5_value=-1.0, std::string arg6_name="", float arg6_value=-1.0)
Definition: Logger.cpp:168
void Log(std::string message, Level level=LevelDebug)
Definition: Logger.cpp:146
static Logger * Instance()
Definition: Logger.cpp:55
Exception when no streams are found in the file.
Definition: Exceptions.h:292
Exception when memory could not be allocated.
Definition: Exceptions.h:355
Coordinate co
This is the primary coordinate.
Definition: Point.h:66
openshot::ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:91
int MaxDecodeWidth() const
Return the current maximum decoded frame width (0 when unlimited).
Definition: ReaderBase.cpp:258
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
Definition: ReaderBase.cpp:161
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
Definition: ReaderBase.cpp:110
int MaxDecodeHeight() const
Return the current maximum decoded frame height (0 when unlimited).
Definition: ReaderBase.cpp:262
bool ApplyOrientationMetadata() const
Return whether readers apply source orientation metadata to returned frames.
Definition: ReaderBase.cpp:274
std::recursive_mutex getFrameMutex
Mutex for multiple threads.
Definition: ReaderBase.h:79
bool HasMaxDecodeSize() const
Return true when a maximum decoded frame size is active.
Definition: ReaderBase.cpp:266
openshot::ClipBase * ParentClip()
Parent clip object of this reader (which can be unparented and NULL)
Definition: ReaderBase.cpp:244
Exception when a reader is closed, and a frame is requested.
Definition: Exceptions.h:370
int DE_LIMIT_WIDTH_MAX
Maximum columns that hardware decode can handle.
Definition: Settings.h:89
int HW_DE_DEVICE_SET
Which GPU to use to decode (0 is the first)
Definition: Settings.h:92
int DE_LIMIT_HEIGHT_MAX
Maximum rows that hardware decode can handle.
Definition: Settings.h:86
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
Definition: Settings.cpp:43
int HARDWARE_DECODER
Use video codec for faster video decoding (if supported)
Definition: Settings.h:71
int preview_height
Optional preview width of timeline image. If your preview window is smaller than the timeline,...
Definition: TimelineBase.h:45
int preview_width
Optional preview width of timeline image. If your preview window is smaller than the timeline,...
Definition: TimelineBase.h:44
This class represents a timeline.
Definition: Timeline.h:154
This namespace is the default namespace for all code in the openshot library.
Definition: AnimatedCurve.h:24
@ SCALE_FIT
Scale the clip until either height or width fills the canvas (with no cropping)
Definition: Enums.h:38
@ SCALE_STRETCH
Scale the clip until both height and width fill the canvas (distort to fit)
Definition: Enums.h:39
@ SCALE_CROP
Scale the clip until both height and width fill the canvas (cropping the overlap)
Definition: Enums.h:37
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
DurationStrategy
This enumeration determines which duration source to favor.
Definition: Enums.h:60
@ VideoPreferred
Prefer the video stream's duration, fallback to audio then container.
@ LongestStream
Use the longest value from video, audio, or container.
@ AudioPreferred
Prefer the audio stream's duration, fallback to video then container.
void ApplyCropResizeScale(Clip *clip, int source_width, int source_height, int &max_width, int &max_height)
Scale the requested max_width / max_height based on the Crop resize amount, capped by source size.
Definition: CropHelpers.cpp:40
QSize AlignPreviewSize(const QSize &size)
Definition: PreviewSize.h:14
const Json::Value stringToJson(const std::string value)
Definition: Json.cpp:16
This struct holds the associated video frame and starting sample # for an audio packet.
Definition: AudioLocation.h:26
bool is_near(AudioLocation location, int samples_per_frame, int64_t amount)
void reset(bool eof)
Definition: FFmpegReader.h:70
int audio_bit_rate
The bit rate of the audio stream (in bytes)
Definition: ReaderBase.h:59
int video_bit_rate
The bit rate of the video stream (in bytes)
Definition: ReaderBase.h:49
bool has_single_image
Determines if this file only contains a single image.
Definition: ReaderBase.h:42
float duration
Length of time (in seconds)
Definition: ReaderBase.h:43
openshot::Fraction audio_timebase
The audio timebase determines how long each audio packet should be played.
Definition: ReaderBase.h:64
int width
The width of the video (in pixesl)
Definition: ReaderBase.h:46
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:61
openshot::Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: ReaderBase.h:48
openshot::Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3)
Definition: ReaderBase.h:51
int height
The height of the video (in pixels)
Definition: ReaderBase.h:45
int pixel_format
The pixel format (i.e. YUV420P, RGB24, etc...)
Definition: ReaderBase.h:47
int64_t video_length
The number of frames in the video stream.
Definition: ReaderBase.h:53
std::string acodec
The name of the audio codec used to encode / decode the video stream.
Definition: ReaderBase.h:58
std::map< std::string, std::string > metadata
An optional map/dictionary of metadata for this reader.
Definition: ReaderBase.h:65
std::string vcodec
The name of the video codec used to encode / decode the video stream.
Definition: ReaderBase.h:52
openshot::Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square)
Definition: ReaderBase.h:50
openshot::ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition: ReaderBase.h:62
bool has_video
Determines if this file has a video stream.
Definition: ReaderBase.h:40
bool has_audio
Determines if this file has an audio stream.
Definition: ReaderBase.h:41
openshot::Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition: ReaderBase.h:55
int video_stream_index
The index of the video stream.
Definition: ReaderBase.h:54
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:60
int audio_stream_index
The index of the audio stream.
Definition: ReaderBase.h:63
int64_t file_size
Size of file (in bytes)
Definition: ReaderBase.h:44