OpenShot Library | libopenshot 1.1.1
Loading...
Searching...
No Matches
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
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.
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number)
Get a frame from the cache.
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...
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.
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).
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
int MaxDecodeHeight() const
Return the current maximum decoded frame height (0 when unlimited).
bool ApplyOrientationMetadata() const
Return whether readers apply source orientation metadata to returned frames.
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.
openshot::ClipBase * ParentClip()
Parent clip object of this reader (which can be unparented and NULL)
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,...
int preview_width
Optional preview width of timeline image. If your preview window is smaller than the timeline,...
This class represents a timeline.
Definition Timeline.h:154
This namespace is the default namespace for all code in the openshot library.
@ 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.
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.
bool is_near(AudioLocation location, int samples_per_frame, int64_t amount)
void reset(bool eof)
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