1 /**
2 * @file
3 * @brief Source file for FFmpegReader class
4 * @author Jonathan Thomas <jonathan@openshot.org>, Fabrice Bellard
5 *
6 * @ref License
7 */
8
9 /* LICENSE
10 *
11 * Copyright (c) 2008-2019 OpenShot Studios, LLC, Fabrice Bellard
12 * (http://www.openshotstudios.com). This file is part of
13 * OpenShot Library (http://www.openshot.org), an open-source project
14 * dedicated to delivering high quality video editing and animation solutions
15 * to the world.
16 *
17 * This file is originally based on the Libavformat API example, and then modified
18 * by the libopenshot project.
19 *
20 * OpenShot Library (libopenshot) is free software: you can redistribute it
21 * and/or modify it under the terms of the GNU Lesser General Public License
22 * as published by the Free Software Foundation, either version 3 of the
23 * License, or (at your option) any later version.
24 *
25 * OpenShot Library (libopenshot) is distributed in the hope that it will be
26 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public License
31 * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
32 */
33
34 #include "FFmpegReader.h"
35 #include "Exceptions.h"
36 #include "Timeline.h"
37
38 #include <thread> // for std::this_thread::sleep_for
39 #include <chrono> // for std::chrono::milliseconds
40
41 #define ENABLE_VAAPI 0
42
43 #if USE_HW_ACCEL
44 #define MAX_SUPPORTED_WIDTH 1950
45 #define MAX_SUPPORTED_HEIGHT 1100
46
47 #if ENABLE_VAAPI
48 #include "libavutil/hwcontext_vaapi.h"
49
50 typedef struct VAAPIDecodeContext {
51 VAProfile va_profile;
52 VAEntrypoint va_entrypoint;
53 VAConfigID va_config;
54 VAContextID va_context;
55
56 #if FF_API_STRUCT_VAAPI_CONTEXT
57 // FF_DISABLE_DEPRECATION_WARNINGS
58 int have_old_context;
59 struct vaapi_context *old_context;
60 AVBufferRef *device_ref;
61 // FF_ENABLE_DEPRECATION_WARNINGS
62 #endif
63
64 AVHWDeviceContext *device;
65 AVVAAPIDeviceContext *hwctx;
66
67 AVHWFramesContext *frames;
68 AVVAAPIFramesContext *hwfc;
69
70 enum AVPixelFormat surface_format;
71 int surface_count;
72 } VAAPIDecodeContext;
73 #endif // ENABLE_VAAPI
74 #endif // USE_HW_ACCEL
75
76
77 using namespace openshot;
78
79 int hw_de_on = 0;
80 #if USE_HW_ACCEL
81 AVPixelFormat hw_de_av_pix_fmt_global = AV_PIX_FMT_NONE;
82 AVHWDeviceType hw_de_av_device_type_global = AV_HWDEVICE_TYPE_NONE;
83 #endif
84
FFmpegReader(const std::string & path,bool inspect_reader)85 FFmpegReader::FFmpegReader(const std::string& path, bool inspect_reader)
86 : last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0),
87 audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false),
88 check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0),
89 prev_samples(0), prev_pts(0), pts_total(0), pts_counter(0), is_duration_known(false), largest_frame_processed(0),
90 current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0),
91 packet(NULL), max_concurrent_frames(OPEN_MP_NUM_PROCESSORS) {
92
93 // Initialize FFMpeg, and register all formats and codecs
94 AV_REGISTER_ALL
95 AVCODEC_REGISTER_ALL
96
97 // Init cache
98 working_cache.SetMaxBytesFromInfo(max_concurrent_frames * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels);
99 missing_frames.SetMaxBytesFromInfo(max_concurrent_frames * 2, info.width, info.height, info.sample_rate, info.channels);
100 final_cache.SetMaxBytesFromInfo(max_concurrent_frames * 2, info.width, info.height, info.sample_rate, info.channels);
101
102 // Open and Close the reader, to populate its attributes (such as height, width, etc...)
103 if (inspect_reader) {
104 Open();
105 Close();
106 }
107 }
108
~FFmpegReader()109 FFmpegReader::~FFmpegReader() {
110 if (is_open)
111 // Auto close reader if not already done
112 Close();
113 }
114
115 // This struct holds the associated video frame and starting sample # for an audio packet.
is_near(AudioLocation location,int samples_per_frame,int64_t amount)116 bool AudioLocation::is_near(AudioLocation location, int samples_per_frame, int64_t amount) {
117 // Is frame even close to this one?
118 if (abs(location.frame - frame) >= 2)
119 // This is too far away to be considered
120 return false;
121
122 // Note that samples_per_frame can vary slightly frame to frame when the
123 // audio sampling rate is not an integer multiple of the video fps.
124 int64_t diff = samples_per_frame * (location.frame - frame) + location.sample_start - sample_start;
125 if (abs(diff) <= amount)
126 // close
127 return true;
128
129 // not close
130 return false;
131 }
132
133 #if USE_HW_ACCEL
134
135 // Get hardware pix format
get_hw_dec_format(AVCodecContext * ctx,const enum AVPixelFormat * pix_fmts)136 static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts)
137 {
138 const enum AVPixelFormat *p;
139
140 for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
141 switch (*p) {
142 #if defined(__unix__)
143 // Linux pix formats
144 case AV_PIX_FMT_VAAPI:
145 hw_de_av_pix_fmt_global = AV_PIX_FMT_VAAPI;
146 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VAAPI;
147 return *p;
148 break;
149 case AV_PIX_FMT_VDPAU:
150 hw_de_av_pix_fmt_global = AV_PIX_FMT_VDPAU;
151 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VDPAU;
152 return *p;
153 break;
154 #endif
155 #if defined(_WIN32)
156 // Windows pix formats
157 case AV_PIX_FMT_DXVA2_VLD:
158 hw_de_av_pix_fmt_global = AV_PIX_FMT_DXVA2_VLD;
159 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_DXVA2;
160 return *p;
161 break;
162 case AV_PIX_FMT_D3D11:
163 hw_de_av_pix_fmt_global = AV_PIX_FMT_D3D11;
164 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_D3D11VA;
165 return *p;
166 break;
167 #endif
168 #if defined(__APPLE__)
169 // Apple pix formats
170 case AV_PIX_FMT_VIDEOTOOLBOX:
171 hw_de_av_pix_fmt_global = AV_PIX_FMT_VIDEOTOOLBOX;
172 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
173 return *p;
174 break;
175 #endif
176 // Cross-platform pix formats
177 case AV_PIX_FMT_CUDA:
178 hw_de_av_pix_fmt_global = AV_PIX_FMT_CUDA;
179 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_CUDA;
180 return *p;
181 break;
182 case AV_PIX_FMT_QSV:
183 hw_de_av_pix_fmt_global = AV_PIX_FMT_QSV;
184 hw_de_av_device_type_global = AV_HWDEVICE_TYPE_QSV;
185 return *p;
186 break;
187 default:
188 // This is only here to silence unused-enum warnings
189 break;
190 }
191 }
192 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::get_hw_dec_format (Unable to decode this file using hardware decode)");
193 return AV_PIX_FMT_NONE;
194 }
195
IsHardwareDecodeSupported(int codecid)196 int FFmpegReader::IsHardwareDecodeSupported(int codecid)
197 {
198 int ret;
199 switch (codecid) {
200 case AV_CODEC_ID_H264:
201 case AV_CODEC_ID_MPEG2VIDEO:
202 case AV_CODEC_ID_VC1:
203 case AV_CODEC_ID_WMV1:
204 case AV_CODEC_ID_WMV2:
205 case AV_CODEC_ID_WMV3:
206 ret = 1;
207 break;
208 default :
209 ret = 0;
210 break;
211 }
212 return ret;
213 }
214 #endif // USE_HW_ACCEL
215
Open()216 void FFmpegReader::Open() {
217 // Open reader if not already open
218 if (!is_open) {
219 // Initialize format context
220 pFormatCtx = NULL;
221 {
222 hw_de_on = (openshot::Settings::Instance()->HARDWARE_DECODER == 0 ? 0 : 1);
223 }
224
225 // Open video file
226 if (avformat_open_input(&pFormatCtx, path.c_str(), NULL, NULL) != 0)
227 throw InvalidFile("File could not be opened.", path);
228
229 // Retrieve stream information
230 if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
231 throw NoStreamsFound("No streams found in file.", path);
232
233 videoStream = -1;
234 audioStream = -1;
235 // Loop through each stream, and identify the video and audio stream index
236 for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
237 // Is this a video stream?
238 if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
239 videoStream = i;
240 }
241 // Is this an audio stream?
242 if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
243 audioStream = i;
244 }
245 }
246 if (videoStream == -1 && audioStream == -1)
247 throw NoStreamsFound("No video or audio streams found in this file.", path);
248
249 // Is there a video stream?
250 if (videoStream != -1) {
251 // Set the stream index
252 info.video_stream_index = videoStream;
253
254 // Set the codec and codec context pointers
255 pStream = pFormatCtx->streams[videoStream];
256
257 // Find the codec ID from stream
258 AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(pStream);
259
260 // Get codec and codec context from stream
261 AVCodec *pCodec = avcodec_find_decoder(codecId);
262 AVDictionary *opts = NULL;
263 int retry_decode_open = 2;
264 // If hw accel is selected but hardware cannot handle repeat with software decoding
265 do {
266 pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec);
267 #if USE_HW_ACCEL
268 if (hw_de_on && (retry_decode_open==2)) {
269 // Up to here no decision is made if hardware or software decode
270 hw_de_supported = IsHardwareDecodeSupported(pCodecCtx->codec_id);
271 }
272 #endif
273 retry_decode_open = 0;
274
275 // Set number of threads equal to number of processors (not to exceed 16)
276 pCodecCtx->thread_count = std::min(FF_NUM_PROCESSORS, 16);
277
278 if (pCodec == NULL) {
279 throw InvalidCodec("A valid video codec could not be found for this file.", path);
280 }
281
282 // Init options
283 av_dict_set(&opts, "strict", "experimental", 0);
284 #if USE_HW_ACCEL
285 if (hw_de_on && hw_de_supported) {
286 // Open Hardware Acceleration
287 int i_decoder_hw = 0;
288 char adapter[256];
289 char *adapter_ptr = NULL;
290 int adapter_num;
291 adapter_num = openshot::Settings::Instance()->HW_DE_DEVICE_SET;
292 fprintf(stderr, "Hardware decoding device number: %d\n", adapter_num);
293
294 // Set hardware pix format (callback)
295 pCodecCtx->get_format = get_hw_dec_format;
296
297 if (adapter_num < 3 && adapter_num >=0) {
298 #if defined(__unix__)
299 snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128);
300 adapter_ptr = adapter;
301 i_decoder_hw = openshot::Settings::Instance()->HARDWARE_DECODER;
302 switch (i_decoder_hw) {
303 case 1:
304 hw_de_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
305 break;
306 case 2:
307 hw_de_av_device_type = AV_HWDEVICE_TYPE_CUDA;
308 break;
309 case 6:
310 hw_de_av_device_type = AV_HWDEVICE_TYPE_VDPAU;
311 break;
312 case 7:
313 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
314 break;
315 default:
316 hw_de_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
317 break;
318 }
319
320 #elif defined(_WIN32)
321 adapter_ptr = NULL;
322 i_decoder_hw = openshot::Settings::Instance()->HARDWARE_DECODER;
323 switch (i_decoder_hw) {
324 case 2:
325 hw_de_av_device_type = AV_HWDEVICE_TYPE_CUDA;
326 break;
327 case 3:
328 hw_de_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
329 break;
330 case 4:
331 hw_de_av_device_type = AV_HWDEVICE_TYPE_D3D11VA;
332 break;
333 case 7:
334 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
335 break;
336 default:
337 hw_de_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
338 break;
339 }
340 #elif defined(__APPLE__)
341 adapter_ptr = NULL;
342 i_decoder_hw = openshot::Settings::Instance()->HARDWARE_DECODER;
343 switch (i_decoder_hw) {
344 case 5:
345 hw_de_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
346 break;
347 case 7:
348 hw_de_av_device_type = AV_HWDEVICE_TYPE_QSV;
349 break;
350 default:
351 hw_de_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
352 break;
353 }
354 #endif
355
356 } else {
357 adapter_ptr = NULL; // Just to be sure
358 }
359
360 // Check if it is there and writable
361 #if defined(__unix__)
362 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
363 #elif defined(_WIN32)
364 if( adapter_ptr != NULL ) {
365 #elif defined(__APPLE__)
366 if( adapter_ptr != NULL ) {
367 #else
368 if( adapter_ptr != NULL ) {
369 #endif
370 ZmqLogger::Instance()->AppendDebugMethod("Decode Device present using device");
371 }
372 else {
373 adapter_ptr = NULL; // use default
374 ZmqLogger::Instance()->AppendDebugMethod("Decode Device not present using default");
375 }
376
377 hw_device_ctx = NULL;
378 // Here the first hardware initialisations are made
379 if (av_hwdevice_ctx_create(&hw_device_ctx, hw_de_av_device_type, adapter_ptr, NULL, 0) >= 0) {
380 if (!(pCodecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx))) {
381 throw InvalidCodec("Hardware device reference create failed.", path);
382 }
383
384 /*
385 av_buffer_unref(&ist->hw_frames_ctx);
386 ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
387 if (!ist->hw_frames_ctx) {
388 av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA frames context\n");
389 return AVERROR(ENOMEM);
390 }
391
392 frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data;
393
394 frames_ctx->format = AV_PIX_FMT_CUDA;
395 frames_ctx->sw_format = avctx->sw_pix_fmt;
396 frames_ctx->width = avctx->width;
397 frames_ctx->height = avctx->height;
398
399 av_log(avctx, AV_LOG_DEBUG, "Initializing CUDA frames context: sw_format = %s, width = %d, height = %d\n",
400 av_get_pix_fmt_name(frames_ctx->sw_format), frames_ctx->width, frames_ctx->height);
401
402
403 ret = av_hwframe_ctx_init(pCodecCtx->hw_device_ctx);
404 ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
405 if (ret < 0) {
406 av_log(avctx, AV_LOG_ERROR, "Error initializing a CUDA frame pool\n");
407 return ret;
408 }
409 */
410 }
411 else {
412 throw InvalidCodec("Hardware device create failed.", path);
413 }
414 }
415 #endif // USE_HW_ACCEL
416
417 // Disable per-frame threading for album arts
418 // Using FF_THREAD_FRAME adds one frame decoding delay per thread,
419 // but there's only one frame in this case.
420 if (HasAlbumArt())
421 {
422 pCodecCtx->thread_type &= ~FF_THREAD_FRAME;
423 }
424
425 // Open video codec
426 if (avcodec_open2(pCodecCtx, pCodec, &opts) < 0)
427 throw InvalidCodec("A video codec was found, but could not be opened.", path);
428
429 #if USE_HW_ACCEL
430 if (hw_de_on && hw_de_supported) {
431 AVHWFramesConstraints *constraints = NULL;
432 void *hwconfig = NULL;
433 hwconfig = av_hwdevice_hwconfig_alloc(hw_device_ctx);
434
435 // TODO: needs va_config!
436 #if ENABLE_VAAPI
437 ((AVVAAPIHWConfig *)hwconfig)->config_id = ((VAAPIDecodeContext *)(pCodecCtx->priv_data))->va_config;
438 constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx,hwconfig);
439 #endif // ENABLE_VAAPI
440 if (constraints) {
441 if (pCodecCtx->coded_width < constraints->min_width ||
442 pCodecCtx->coded_height < constraints->min_height ||
443 pCodecCtx->coded_width > constraints->max_width ||
444 pCodecCtx->coded_height > constraints->max_height) {
445 ZmqLogger::Instance()->AppendDebugMethod("DIMENSIONS ARE TOO LARGE for hardware acceleration\n");
446 hw_de_supported = 0;
447 retry_decode_open = 1;
448 AV_FREE_CONTEXT(pCodecCtx);
449 if (hw_device_ctx) {
450 av_buffer_unref(&hw_device_ctx);
451 hw_device_ctx = NULL;
452 }
453 }
454 else {
455 // All is just peachy
456 ZmqLogger::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);
457 retry_decode_open = 0;
458 }
459 av_hwframe_constraints_free(&constraints);
460 if (hwconfig) {
461 av_freep(&hwconfig);
462 }
463 }
464 else {
465 int max_h, max_w;
466 //max_h = ((getenv( "LIMIT_HEIGHT_MAX" )==NULL) ? MAX_SUPPORTED_HEIGHT : atoi(getenv( "LIMIT_HEIGHT_MAX" )));
467 max_h = openshot::Settings::Instance()->DE_LIMIT_HEIGHT_MAX;
468 //max_w = ((getenv( "LIMIT_WIDTH_MAX" )==NULL) ? MAX_SUPPORTED_WIDTH : atoi(getenv( "LIMIT_WIDTH_MAX" )));
469 max_w = openshot::Settings::Instance()->DE_LIMIT_WIDTH_MAX;
470 ZmqLogger::Instance()->AppendDebugMethod("Constraints could not be found using default limit\n");
471 //cerr << "Constraints could not be found using default limit\n";
472 if (pCodecCtx->coded_width < 0 ||
473 pCodecCtx->coded_height < 0 ||
474 pCodecCtx->coded_width > max_w ||
475 pCodecCtx->coded_height > max_h ) {
476 ZmqLogger::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);
477 hw_de_supported = 0;
478 retry_decode_open = 1;
479 AV_FREE_CONTEXT(pCodecCtx);
480 if (hw_device_ctx) {
481 av_buffer_unref(&hw_device_ctx);
482 hw_device_ctx = NULL;
483 }
484 }
485 else {
486 ZmqLogger::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);
487 retry_decode_open = 0;
488 }
489 }
490 } // if hw_de_on && hw_de_supported
491 else {
492 ZmqLogger::Instance()->AppendDebugMethod("\nDecode in software is used\n");
493 }
494 #else
495 retry_decode_open = 0;
496 #endif // USE_HW_ACCEL
497 } while (retry_decode_open); // retry_decode_open
498 // Free options
499 av_dict_free(&opts);
500
501 // Update the File Info struct with video details (if a video stream is found)
502 UpdateVideoInfo();
503 }
504
505 // Is there an audio stream?
506 if (audioStream != -1) {
507 // Set the stream index
508 info.audio_stream_index = audioStream;
509
510 // Get a pointer to the codec context for the audio stream
511 aStream = pFormatCtx->streams[audioStream];
512
513 // Find the codec ID from stream
514 AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(aStream);
515
516 // Get codec and codec context from stream
517 AVCodec *aCodec = avcodec_find_decoder(codecId);
518 aCodecCtx = AV_GET_CODEC_CONTEXT(aStream, aCodec);
519
520 // Set number of threads equal to number of processors (not to exceed 16)
521 aCodecCtx->thread_count = std::min(FF_NUM_PROCESSORS, 16);
522
523 if (aCodec == NULL) {
524 throw InvalidCodec("A valid audio codec could not be found for this file.", path);
525 }
526
527 // Init options
528 AVDictionary *opts = NULL;
529 av_dict_set(&opts, "strict", "experimental", 0);
530
531 // Open audio codec
532 if (avcodec_open2(aCodecCtx, aCodec, &opts) < 0)
533 throw InvalidCodec("An audio codec was found, but could not be opened.", path);
534
535 // Free options
536 av_dict_free(&opts);
537
538 // Update the File Info struct with audio details (if an audio stream is found)
539 UpdateAudioInfo();
540 }
541
542 // Add format metadata (if any)
543 AVDictionaryEntry *tag = NULL;
544 while ((tag = av_dict_get(pFormatCtx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
545 QString str_key = tag->key;
546 QString str_value = tag->value;
547 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
548 }
549
550 // Init previous audio location to zero
551 previous_packet_location.frame = -1;
552 previous_packet_location.sample_start = 0;
553
554 // Adjust cache size based on size of frame and audio
555 working_cache.SetMaxBytesFromInfo(max_concurrent_frames * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels);
556 missing_frames.SetMaxBytesFromInfo(max_concurrent_frames * 2, info.width, info.height, info.sample_rate, info.channels);
557 final_cache.SetMaxBytesFromInfo(max_concurrent_frames * 2, info.width, info.height, info.sample_rate, info.channels);
558
559 // Mark as "open"
560 is_open = true;
561 }
562 }
563
564 void FFmpegReader::Close() {
565 // Close all objects, if reader is 'open'
566 if (is_open) {
567 // Mark as "closed"
568 is_open = false;
569
570 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::Close");
571
572 if (packet) {
573 // Remove previous packet before getting next one
574 RemoveAVPacket(packet);
575 packet = NULL;
576 }
577
578 // Close the codec
579 if (info.has_video) {
580 avcodec_flush_buffers(pCodecCtx);
581 AV_FREE_CONTEXT(pCodecCtx);
582 #if USE_HW_ACCEL
583 if (hw_de_on) {
584 if (hw_device_ctx) {
585 av_buffer_unref(&hw_device_ctx);
586 hw_device_ctx = NULL;
587 }
588 }
589 #endif // USE_HW_ACCEL
590 }
591 if (info.has_audio) {
592 avcodec_flush_buffers(aCodecCtx);
593 AV_FREE_CONTEXT(aCodecCtx);
594 }
595
596 // Clear final cache
597 final_cache.Clear();
598 working_cache.Clear();
599 missing_frames.Clear();
600
601 // Clear processed lists
602 {
603 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
604 processed_video_frames.clear();
605 processed_audio_frames.clear();
606 processing_video_frames.clear();
607 processing_audio_frames.clear();
608 missing_audio_frames.clear();
609 missing_video_frames.clear();
610 missing_audio_frames_source.clear();
611 missing_video_frames_source.clear();
612 checked_frames.clear();
613 }
614
615 // Close the video file
616 avformat_close_input(&pFormatCtx);
617 av_freep(&pFormatCtx);
618
619 // Reset some variables
620 last_frame = 0;
621 largest_frame_processed = 0;
622 seek_audio_frame_found = 0;
623 seek_video_frame_found = 0;
624 current_video_frame = 0;
625 has_missing_frames = false;
626
627 last_video_frame.reset();
628 }
629 }
630
631 bool FFmpegReader::HasAlbumArt() {
632 // Check if the video stream we use is an attached picture
633 // This won't return true if the file has a cover image as a secondary stream
634 // like an MKV file with an attached image file
635 return pFormatCtx && videoStream >= 0 && pFormatCtx->streams[videoStream]
636 && (pFormatCtx->streams[videoStream]->disposition & AV_DISPOSITION_ATTACHED_PIC);
637 }
638
639 void FFmpegReader::UpdateAudioInfo() {
640 // Set values of FileInfo struct
641 info.has_audio = true;
642 info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
643 info.acodec = aCodecCtx->codec->name;
644 info.channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
645 if (AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout == 0)
646 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout = av_get_default_channel_layout(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels);
647 info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout;
648 info.sample_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->sample_rate;
649 info.audio_bit_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->bit_rate;
650
651 // Set audio timebase
652 info.audio_timebase.num = aStream->time_base.num;
653 info.audio_timebase.den = aStream->time_base.den;
654
655 // Get timebase of audio stream (if valid) and greater than the current duration
656 if (aStream->duration > 0.0f && aStream->duration > info.duration)
657 info.duration = aStream->duration * info.audio_timebase.ToDouble();
658
659 // Check for an invalid video length
660 if (info.has_video && info.video_length <= 0) {
661 // Calculate the video length from the audio duration
662 info.video_length = info.duration * info.fps.ToDouble();
663 }
664
665 // Set video timebase (if no video stream was found)
666 if (!info.has_video) {
667 // Set a few important default video settings (so audio can be divided into frames)
668 info.fps.num = 24;
669 info.fps.den = 1;
670 info.video_timebase.num = 1;
671 info.video_timebase.den = 24;
672 info.video_length = info.duration * info.fps.ToDouble();
673 info.width = 720;
674 info.height = 480;
675 }
676
677 // Fix invalid video lengths for certain types of files (MP3 for example)
678 if (info.has_video && ((info.duration * info.fps.ToDouble()) - info.video_length > 60)) {
679 info.video_length = info.duration * info.fps.ToDouble();
680 }
681
682 // Add audio metadata (if any found)
683 AVDictionaryEntry *tag = NULL;
684 while ((tag = av_dict_get(aStream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
685 QString str_key = tag->key;
686 QString str_value = tag->value;
687 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
688 }
689 }
690
691 void FFmpegReader::UpdateVideoInfo() {
692 if (check_fps)
693 // Already initialized all the video metadata, no reason to do it again
694 return;
695
696 // Set values of FileInfo struct
697 info.has_video = true;
698 info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
699 info.height = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->height;
700 info.width = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->width;
701 info.vcodec = pCodecCtx->codec->name;
702 info.video_bit_rate = (pFormatCtx->bit_rate / 8);
703
704 // Frame rate from the container and codec
705 AVRational framerate = av_guess_frame_rate(pFormatCtx, pStream, NULL);
706 info.fps.num = framerate.num;
707 info.fps.den = framerate.den;
708
709 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo", "info.fps.num", info.fps.num, "info.fps.den", info.fps.den);
710
711 // TODO: remove excessive debug info in the next releases
712 // The debug info below is just for comparison and troubleshooting on users side during the transition period
713 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo (pStream->avg_frame_rate)", "num", pStream->avg_frame_rate.num, "den", pStream->avg_frame_rate.den);
714
715 if (pStream->sample_aspect_ratio.num != 0) {
716 info.pixel_ratio.num = pStream->sample_aspect_ratio.num;
717 info.pixel_ratio.den = pStream->sample_aspect_ratio.den;
718 } else if (AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num != 0) {
719 info.pixel_ratio.num = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num;
720 info.pixel_ratio.den = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.den;
721 } else {
722 info.pixel_ratio.num = 1;
723 info.pixel_ratio.den = 1;
724 }
725 info.pixel_format = AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
726
727 // Calculate the DAR (display aspect ratio)
728 Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den);
729
730 // Reduce size fraction
731 size.Reduce();
732
733 // Set the ratio based on the reduced fraction
734 info.display_ratio.num = size.num;
735 info.display_ratio.den = size.den;
736
737 // Get scan type and order from codec context/params
738 if (!check_interlace) {
739 check_interlace = true;
740 AVFieldOrder field_order = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->field_order;
741 switch(field_order) {
742 case AV_FIELD_PROGRESSIVE:
743 info.interlaced_frame = false;
744 break;
745 case AV_FIELD_TT:
746 case AV_FIELD_TB:
747 info.interlaced_frame = true;
748 info.top_field_first = true;
749 break;
750 case AV_FIELD_BT:
751 case AV_FIELD_BB:
752 info.interlaced_frame = true;
753 info.top_field_first = false;
754 break;
755 case AV_FIELD_UNKNOWN:
756 // Check again later?
757 check_interlace = false;
758 break;
759 }
760 // check_interlace will prevent these checks being repeated,
761 // unless it was cleared because we got an AV_FIELD_UNKNOWN response.
762 }
763
764 // Set the video timebase
765 info.video_timebase.num = pStream->time_base.num;
766 info.video_timebase.den = pStream->time_base.den;
767
768 // Set the duration in seconds, and video length (# of frames)
769 info.duration = pStream->duration * info.video_timebase.ToDouble();
770
771 // Check for valid duration (if found)
772 if (info.duration <= 0.0f && pFormatCtx->duration >= 0)
773 // Use the format's duration
774 info.duration = float(pFormatCtx->duration) / AV_TIME_BASE;
775
776 // Calculate duration from filesize and bitrate (if any)
777 if (info.duration <= 0.0f && info.video_bit_rate > 0 && info.file_size > 0)
778 // Estimate from bitrate, total bytes, and framerate
779 info.duration = float(info.file_size) / info.video_bit_rate;
780
781 // No duration found in stream of file
782 if (info.duration <= 0.0f) {
783 // No duration is found in the video stream
784 info.duration = -1;
785 info.video_length = -1;
786 is_duration_known = false;
787 } else {
788 // Yes, a duration was found
789 is_duration_known = true;
790
791 // Calculate number of frames
792 info.video_length = round(info.duration * info.fps.ToDouble());
793 }
794
795 // Override an invalid framerate
796 if (info.fps.ToFloat() > 240.0f || (info.fps.num <= 0 || info.fps.den <= 0) || info.video_length <= 0) {
797 // Calculate FPS, duration, video bit rate, and video length manually
798 // by scanning through all the video stream packets
799 CheckFPS();
800 }
801
802 // Add video metadata (if any)
803 AVDictionaryEntry *tag = NULL;
804 while ((tag = av_dict_get(pStream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
805 QString str_key = tag->key;
806 QString str_value = tag->value;
807 info.metadata[str_key.toStdString()] = str_value.trimmed().toStdString();
808 }
809 }
810
811 bool FFmpegReader::GetIsDurationKnown() {
812 return this->is_duration_known;
813 }
814
815 std::shared_ptr<Frame> FFmpegReader::GetFrame(int64_t requested_frame) {
816 // Check for open reader (or throw exception)
817 if (!is_open)
818 throw ReaderClosed("The FFmpegReader is closed. Call Open() before calling this method.", path);
819
820 // Adjust for a requested frame that is too small or too large
821 if (requested_frame < 1)
822 requested_frame = 1;
823 if (requested_frame > info.video_length && is_duration_known)
824 requested_frame = info.video_length;
825 if (info.has_video && info.video_length == 0)
826 // Invalid duration of video file
827 throw InvalidFile("Could not detect the duration of the video or audio stream.", path);
828
829 // Debug output
830 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "requested_frame", requested_frame, "last_frame", last_frame);
831
832 // Check the cache for this frame
833 std::shared_ptr<Frame> frame = final_cache.GetFrame(requested_frame);
834 if (frame) {
835 // Debug output
836 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "returned cached frame", requested_frame);
837
838 // Return the cached frame
839 return frame;
840 } else {
841 // Check the cache a 2nd time (due to a potential previous lock)
842 frame = final_cache.GetFrame(requested_frame);
843 if (frame) {
844 // Debug output
845 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "returned cached frame on 2nd look", requested_frame);
846
847 // Return the cached frame
848 } else {
849 // Frame is not in cache
850 // Reset seek count
851 seek_count = 0;
852
853 // Check for first frame (always need to get frame 1 before other frames, to correctly calculate offsets)
854 if (last_frame == 0 && requested_frame != 1)
855 // Get first frame
856 ReadStream(1);
857
858 // Are we within X frames of the requested frame?
859 int64_t diff = requested_frame - last_frame;
860 if (diff >= 1 && diff <= 20) {
861 // Continue walking the stream
862 frame = ReadStream(requested_frame);
863 } else {
864 // Greater than 30 frames away, or backwards, we need to seek to the nearest key frame
865 if (enable_seek)
866 // Only seek if enabled
867 Seek(requested_frame);
868
869 else if (!enable_seek && diff < 0) {
870 // Start over, since we can't seek, and the requested frame is smaller than our position
871 Close();
872 Open();
873 }
874
875 // Then continue walking the stream
876 frame = ReadStream(requested_frame);
877 }
878 }
879 return frame;
880 }
881 }
882
883 // Read the stream until we find the requested Frame
884 std::shared_ptr<Frame> FFmpegReader::ReadStream(int64_t requested_frame) {
885 // Allocate video frame
886 bool end_of_stream = false;
887 bool check_seek = false;
888 bool frame_finished = false;
889 int packet_error = -1;
890
891 // Minimum number of packets to process (for performance reasons)
892 int packets_processed = 0;
893 int minimum_packets = 1;
894 int max_packets = 4096;
895
896 // Debug output
897 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream", "requested_frame", requested_frame, "max_concurrent_frames", max_concurrent_frames);
898
899 // Loop through the stream until the correct frame is found
900 while (true) {
901 // Get the next packet into a local variable called packet
902 packet_error = GetNextPacket();
903
904 int processing_video_frames_size = 0;
905 int processing_audio_frames_size = 0;
906 {
907 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
908 processing_video_frames_size = processing_video_frames.size();
909 processing_audio_frames_size = processing_audio_frames.size();
910 }
911
912 // Wait if too many frames are being processed
913 while (processing_video_frames_size + processing_audio_frames_size >= minimum_packets) {
914 std::this_thread::sleep_for(std::chrono::milliseconds(3));
915 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
916 processing_video_frames_size = processing_video_frames.size();
917 processing_audio_frames_size = processing_audio_frames.size();
918 }
919
920 // Get the next packet (if any)
921 if (packet_error < 0) {
922 // Break loop when no more packets found
923 end_of_stream = true;
924 break;
925 }
926
927 // Debug output
928 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (GetNextPacket)", "requested_frame", requested_frame, "processing_video_frames_size", processing_video_frames_size, "processing_audio_frames_size", processing_audio_frames_size, "minimum_packets", minimum_packets, "packets_processed", packets_processed, "is_seeking", is_seeking);
929
930 // Video packet
931 if (info.has_video && packet->stream_index == videoStream) {
932 // Reset this counter, since we have a video packet
933 num_packets_since_video_frame = 0;
934
935 // Check the status of a seek (if any)
936 if (is_seeking) {
937 check_seek = CheckSeek(true);
938 } else {
939 check_seek = false;
940 }
941
942 if (check_seek) {
943 // Jump to the next iteration of this loop
944 continue;
945 }
946
947 // Packet may become NULL on Close inside Seek if CheckSeek returns false
948 if (!packet) {
949 // Jump to the next iteration of this loop
950 continue;
951 }
952
953 // Get the AVFrame from the current packet
954 frame_finished = GetAVFrame();
955
956 // Check if the AVFrame is finished and set it
957 if (frame_finished) {
958 // Update PTS / Frame Offset (if any)
959 UpdatePTSOffset(true);
960
961 // Process Video Packet
962 ProcessVideoPacket(requested_frame);
963 }
964
965 }
966 // Audio packet
967 else if (info.has_audio && packet->stream_index == audioStream) {
968 // Increment this (to track # of packets since the last video packet)
969 num_packets_since_video_frame++;
970
971 // Check the status of a seek (if any)
972 if (is_seeking) {
973 check_seek = CheckSeek(false);
974 } else {
975 check_seek = false;
976 }
977
978 if (check_seek) {
979 // Jump to the next iteration of this loop
980 continue;
981 }
982
983 // Packet may become NULL on Close inside Seek if CheckSeek returns false
984 if (!packet) {
985 // Jump to the next iteration of this loop
986 continue;
987 }
988
989 // Update PTS / Frame Offset (if any)
990 UpdatePTSOffset(false);
991
992 // Determine related video frame and starting sample # from audio PTS
993 AudioLocation location = GetAudioPTSLocation(packet->pts);
994
995 // Process Audio Packet
996 ProcessAudioPacket(requested_frame, location.frame, location.sample_start);
997 }
998
999 // Check if working frames are 'finished'
1000 if (!is_seeking) {
1001 // Check for final frames
1002 CheckWorkingFrames(false, requested_frame);
1003 }
1004
1005 // Check if requested 'final' frame is available
1006 bool is_cache_found = (final_cache.GetFrame(requested_frame) != NULL);
1007
1008 // Increment frames processed
1009 packets_processed++;
1010
1011 // Break once the frame is found
1012 if ((is_cache_found && packets_processed >= minimum_packets) || packets_processed > max_packets)
1013 break;
1014
1015 } // end while
1016
1017 // Debug output
1018 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream (Completed)", "packets_processed", packets_processed, "end_of_stream", end_of_stream, "largest_frame_processed", largest_frame_processed, "Working Cache Count", working_cache.Count());
1019
1020 // End of stream?
1021 if (end_of_stream)
1022 // Mark the any other working frames as 'finished'
1023 CheckWorkingFrames(end_of_stream, requested_frame);
1024
1025 // Return requested frame (if found)
1026 std::shared_ptr<Frame> frame = final_cache.GetFrame(requested_frame);
1027 if (frame)
1028 // Return prepared frame
1029 return frame;
1030 else {
1031
1032 // Check if largest frame is still cached
1033 frame = final_cache.GetFrame(largest_frame_processed);
1034 if (frame) {
1035 // return the largest processed frame (assuming it was the last in the video file)
1036 return frame;
1037 } else {
1038 // The largest processed frame is no longer in cache, return a blank frame
1039 std::shared_ptr<Frame> f = CreateFrame(largest_frame_processed);
1040 f->AddColor(info.width, info.height, "#000");
1041 return f;
1042 }
1043 }
1044
1045 }
1046
1047 // Get the next packet (if any)
1048 int FFmpegReader::GetNextPacket() {
1049 int found_packet = 0;
1050 AVPacket *next_packet;
1051 next_packet = new AVPacket();
1052 found_packet = av_read_frame(pFormatCtx, next_packet);
1053
1054 if (packet) {
1055 // Remove previous packet before getting next one
1056 RemoveAVPacket(packet);
1057 packet = NULL;
1058 }
1059 if (found_packet >= 0) {
1060 // Update current packet pointer
1061 packet = next_packet;
1062 } else {
1063 delete next_packet;
1064 }
1065 // Return if packet was found (or error number)
1066 return found_packet;
1067 }
1068
1069 // Get an AVFrame (if any)
1070 bool FFmpegReader::GetAVFrame() {
1071 int frameFinished = -1;
1072 int ret = 0;
1073
1074 // Decode video frame
1075 AVFrame *next_frame = AV_ALLOCATE_FRAME();
1076
1077 #if IS_FFMPEG_3_2
1078 frameFinished = 0;
1079 ret = avcodec_send_packet(pCodecCtx, packet);
1080
1081 #if USE_HW_ACCEL
1082 // Get the format from the variables set in get_hw_dec_format
1083 hw_de_av_pix_fmt = hw_de_av_pix_fmt_global;
1084 hw_de_av_device_type = hw_de_av_device_type_global;
1085 #endif // USE_HW_ACCEL
1086 if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1087 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Packet not sent)");
1088 }
1089 else {
1090 AVFrame *next_frame2;
1091 #if USE_HW_ACCEL
1092 if (hw_de_on && hw_de_supported) {
1093 next_frame2 = AV_ALLOCATE_FRAME();
1094 }
1095 else
1096 #endif // USE_HW_ACCEL
1097 {
1098 next_frame2 = next_frame;
1099 }
1100 pFrame = AV_ALLOCATE_FRAME();
1101 while (ret >= 0) {
1102 ret = avcodec_receive_frame(pCodecCtx, next_frame2);
1103 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1104 break;
1105 }
1106 if (ret != 0) {
1107 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (invalid return frame received)");
1108 }
1109 #if USE_HW_ACCEL
1110 if (hw_de_on && hw_de_supported) {
1111 int err;
1112 if (next_frame2->format == hw_de_av_pix_fmt) {
1113 next_frame->format = AV_PIX_FMT_YUV420P;
1114 if ((err = av_hwframe_transfer_data(next_frame,next_frame2,0)) < 0) {
1115 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Failed to transfer data to output frame)");
1116 }
1117 if ((err = av_frame_copy_props(next_frame,next_frame2)) < 0) {
1118 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Failed to copy props to output frame)");
1119 }
1120 }
1121 }
1122 else
1123 #endif // USE_HW_ACCEL
1124 { // No hardware acceleration used -> no copy from GPU memory needed
1125 next_frame = next_frame2;
1126 }
1127
1128 // TODO also handle possible further frames
1129 // Use only the first frame like avcodec_decode_video2
1130 if (frameFinished == 0 ) {
1131 frameFinished = 1;
1132 av_image_alloc(pFrame->data, pFrame->linesize, info.width, info.height, (AVPixelFormat)(pStream->codecpar->format), 1);
1133 av_image_copy(pFrame->data, pFrame->linesize, (const uint8_t**)next_frame->data, next_frame->linesize,
1134 (AVPixelFormat)(pStream->codecpar->format), info.width, info.height);
1135 }
1136 }
1137 #if USE_HW_ACCEL
1138 if (hw_de_on && hw_de_supported) {
1139 AV_FREE_FRAME(&next_frame2);
1140 }
1141 #endif // USE_HW_ACCEL
1142 }
1143 #else
1144 avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
1145
1146 // always allocate pFrame (because we do that in the ffmpeg >= 3.2 as well); it will always be freed later
1147 pFrame = AV_ALLOCATE_FRAME();
1148
1149 // is frame finished
1150 if (frameFinished) {
1151 // AVFrames are clobbered on the each call to avcodec_decode_video, so we
1152 // must make a copy of the image data before this method is called again.
1153 avpicture_alloc((AVPicture *) pFrame, pCodecCtx->pix_fmt, info.width, info.height);
1154 av_picture_copy((AVPicture *) pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width,
1155 info.height);
1156 }
1157 #endif // IS_FFMPEG_3_2
1158
1159 // deallocate the frame
1160 AV_FREE_FRAME(&next_frame);
1161
1162 // Did we get a video frame?
1163 return frameFinished;
1164 }
1165
1166 // Check the current seek position and determine if we need to seek again
1167 bool FFmpegReader::CheckSeek(bool is_video) {
1168 // Are we seeking for a specific frame?
1169 if (is_seeking) {
1170 // Determine if both an audio and video packet have been decoded since the seek happened.
1171 // If not, allow the ReadStream method to keep looping
1172 if ((is_video_seek && !seek_video_frame_found) || (!is_video_seek && !seek_audio_frame_found))
1173 return false;
1174
1175 // Check for both streams
1176 if ((info.has_video && !seek_video_frame_found) || (info.has_audio && !seek_audio_frame_found))
1177 return false;
1178
1179 // Determine max seeked frame
1180 int64_t max_seeked_frame = seek_audio_frame_found; // determine max seeked frame
1181 if (seek_video_frame_found > max_seeked_frame)
1182 max_seeked_frame = seek_video_frame_found;
1183
1184 // determine if we are "before" the requested frame
1185 if (max_seeked_frame >= seeking_frame) {
1186 // SEEKED TOO FAR
1187 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Too far, seek again)", "is_video_seek", is_video_seek, "max_seeked_frame", max_seeked_frame, "seeking_frame", seeking_frame, "seeking_pts", seeking_pts, "seek_video_frame_found", seek_video_frame_found, "seek_audio_frame_found", seek_audio_frame_found);
1188
1189 // Seek again... to the nearest Keyframe
1190 Seek(seeking_frame - (10 * seek_count * seek_count));
1191 } else {
1192 // SEEK WORKED
1193 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Successful)", "is_video_seek", is_video_seek, "current_pts", packet->pts, "seeking_pts", seeking_pts, "seeking_frame", seeking_frame, "seek_video_frame_found", seek_video_frame_found, "seek_audio_frame_found", seek_audio_frame_found);
1194
1195 // Seek worked, and we are "before" the requested frame
1196 is_seeking = false;
1197 seeking_frame = 0;
1198 seeking_pts = -1;
1199 }
1200 }
1201
1202 // return the pts to seek to (if any)
1203 return is_seeking;
1204 }
1205
1206 // Process a video packet
1207 void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
1208 // Calculate current frame #
1209 int64_t current_frame = ConvertVideoPTStoFrame(GetVideoPTS());
1210
1211 // Track 1st video packet after a successful seek
1212 if (!seek_video_frame_found && is_seeking)
1213 seek_video_frame_found = current_frame;
1214
1215 // Are we close enough to decode the frame? and is this frame # valid?
1216 if ((current_frame < (requested_frame - 20)) or (current_frame == -1)) {
1217 // Remove frame and packet
1218 RemoveAVFrame(pFrame);
1219
1220 // Debug output
1221 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (Skipped)", "requested_frame", requested_frame, "current_frame", current_frame);
1222
1223 // Skip to next frame without decoding or caching
1224 return;
1225 }
1226
1227 // Debug output
1228 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (Before)", "requested_frame", requested_frame, "current_frame", current_frame);
1229
1230 // Init some things local (for OpenMP)
1231 PixelFormat pix_fmt = AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
1232 int height = info.height;
1233 int width = info.width;
1234 int64_t video_length = info.video_length;
1235 AVFrame *my_frame = pFrame;
1236 pFrame = NULL;
1237
1238 // Add video frame to list of processing video frames
1239 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1240 processing_video_frames[current_frame] = current_frame;
1241
1242 // Create variables for a RGB Frame (since most videos are not in RGB, we must convert it)
1243 AVFrame *pFrameRGB = nullptr;
1244 uint8_t *buffer = nullptr;
1245
1246 // Allocate an AVFrame structure
1247 pFrameRGB = AV_ALLOCATE_FRAME();
1248 if (pFrameRGB == nullptr)
1249 throw OutOfMemory("Failed to allocate frame buffer", path);
1250
1251 // Determine the max size of this source image (based on the timeline's size, the scaling mode,
1252 // and the scaling keyframes). This is a performance improvement, to keep the images as small as possible,
1253 // without losing quality. NOTE: We cannot go smaller than the timeline itself, or the add_layer timeline
1254 // method will scale it back to timeline size before scaling it smaller again. This needs to be fixed in
1255 // the future.
1256 int max_width = info.width;
1257 int max_height = info.height;
1258
1259 Clip *parent = (Clip *) ParentClip();
1260 if (parent) {
1261 if (parent->ParentTimeline()) {
1262 // Set max width/height based on parent clip's timeline (if attached to a timeline)
1263 max_width = parent->ParentTimeline()->preview_width;
1264 max_height = parent->ParentTimeline()->preview_height;
1265 }
1266 if (parent->scale == SCALE_FIT || parent->scale == SCALE_STRETCH) {
1267 // Best fit or Stretch scaling (based on max timeline size * scaling keyframes)
1268 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1269 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1270 max_width = std::max(float(max_width), max_width * max_scale_x);
1271 max_height = std::max(float(max_height), max_height * max_scale_y);
1272
1273 } else if (parent->scale == SCALE_CROP) {
1274 // Cropping scale mode (based on max timeline size * cropped size * scaling keyframes)
1275 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1276 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1277 QSize width_size(max_width * max_scale_x,
1278 round(max_width / (float(info.width) / float(info.height))));
1279 QSize height_size(round(max_height / (float(info.height) / float(info.width))),
1280 max_height * max_scale_y);
1281 // respect aspect ratio
1282 if (width_size.width() >= max_width && width_size.height() >= max_height) {
1283 max_width = std::max(max_width, width_size.width());
1284 max_height = std::max(max_height, width_size.height());
1285 } else {
1286 max_width = std::max(max_width, height_size.width());
1287 max_height = std::max(max_height, height_size.height());
1288 }
1289
1290 } else {
1291 // Scale video to equivalent unscaled size
1292 // Since the preview window can change sizes, we want to always
1293 // scale against the ratio of original video size to timeline size
1294 float preview_ratio = 1.0;
1295 if (parent->ParentTimeline()) {
1296 Timeline *t = (Timeline *) parent->ParentTimeline();
1297 preview_ratio = t->preview_width / float(t->info.width);
1298 }
1299 float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
1300 float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
1301 max_width = info.width * max_scale_x * preview_ratio;
1302 max_height = info.height * max_scale_y * preview_ratio;
1303 }
1304 }
1305
1306 // Determine if image needs to be scaled (for performance reasons)
1307 int original_height = height;
1308 if (max_width != 0 && max_height != 0 && max_width < width && max_height < height) {
1309 // Override width and height (but maintain aspect ratio)
1310 float ratio = float(width) / float(height);
1311 int possible_width = round(max_height * ratio);
1312 int possible_height = round(max_width / ratio);
1313
1314 if (possible_width <= max_width) {
1315 // use calculated width, and max_height
1316 width = possible_width;
1317 height = max_height;
1318 } else {
1319 // use max_width, and calculated height
1320 width = max_width;
1321 height = possible_height;
1322 }
1323 }
1324
1325 // Determine required buffer size and allocate buffer
1326 const int bytes_per_pixel = 4;
1327 int buffer_size = width * height * bytes_per_pixel;
1328 buffer = new unsigned char[buffer_size]();
1329
1330 // Copy picture data from one AVFrame (or AVPicture) to another one.
1331 AV_COPY_PICTURE_DATA(pFrameRGB, buffer, PIX_FMT_RGBA, width, height);
1332
1333 int scale_mode = SWS_FAST_BILINEAR;
1334 if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) {
1335 scale_mode = SWS_BICUBIC;
1336 }
1337 SwsContext *img_convert_ctx = sws_getContext(info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), width,
1338 height, PIX_FMT_RGBA, scale_mode, NULL, NULL, NULL);
1339
1340 // Resize / Convert to RGB
1341 sws_scale(img_convert_ctx, my_frame->data, my_frame->linesize, 0,
1342 original_height, pFrameRGB->data, pFrameRGB->linesize);
1343
1344 // Create or get the existing frame object
1345 std::shared_ptr<Frame> f = CreateFrame(current_frame);
1346
1347 // Add Image data to frame
1348 if (!ffmpeg_has_alpha(AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx))) {
1349 // Add image with no alpha channel, Speed optimization
1350 f->AddImage(width, height, bytes_per_pixel, QImage::Format_RGBA8888_Premultiplied, buffer);
1351 } else {
1352 // Add image with alpha channel (this will be converted to premultipled when needed, but is slower)
1353 f->AddImage(width, height, bytes_per_pixel, QImage::Format_RGBA8888, buffer);
1354 }
1355
1356 // Update working cache
1357 working_cache.Add(f);
1358
1359 // Keep track of last last_video_frame
1360 last_video_frame = f;
1361
1362 // Free the RGB image
1363 AV_FREE_FRAME(&pFrameRGB);
1364
1365 // Remove frame and packet
1366 RemoveAVFrame(my_frame);
1367 sws_freeContext(img_convert_ctx);
1368
1369 // Remove video frame from list of processing video frames
1370 {
1371 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1372 processing_video_frames.erase(current_frame);
1373 processed_video_frames[current_frame] = current_frame;
1374 }
1375
1376 // Debug output
1377 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (After)", "requested_frame", requested_frame, "current_frame", current_frame, "f->number", f->number);
1378 }
1379
1380 // Process an audio packet
1381 void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_frame, int starting_sample) {
1382 // Track 1st audio packet after a successful seek
1383 if (!seek_audio_frame_found && is_seeking)
1384 seek_audio_frame_found = target_frame;
1385
1386 // Are we close enough to decode the frame's audio?
1387 if (target_frame < (requested_frame - 20)) {
1388 // Debug output
1389 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Skipped)", "requested_frame", requested_frame, "target_frame", target_frame, "starting_sample", starting_sample);
1390
1391 // Skip to next frame without decoding or caching
1392 return;
1393 }
1394
1395 // Debug output
1396 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Before)", "requested_frame", requested_frame, "target_frame", target_frame, "starting_sample", starting_sample);
1397
1398 // Init an AVFrame to hold the decoded audio samples
1399 int frame_finished = 0;
1400 AVFrame *audio_frame = AV_ALLOCATE_FRAME();
1401 AV_RESET_FRAME(audio_frame);
1402
1403 int packet_samples = 0;
1404 int data_size = 0;
1405
1406 #if IS_FFMPEG_3_2
1407 int ret = 0;
1408 frame_finished = 1;
1409 while((packet->size > 0 || (!packet->data && frame_finished)) && ret >= 0) {
1410 frame_finished = 0;
1411 ret = avcodec_send_packet(aCodecCtx, packet);
1412 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1413 avcodec_send_packet(aCodecCtx, NULL);
1414 break;
1415 }
1416 if (ret >= 0)
1417 packet->size = 0;
1418 ret = avcodec_receive_frame(aCodecCtx, audio_frame);
1419 if (ret >= 0)
1420 frame_finished = 1;
1421 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1422 avcodec_flush_buffers(aCodecCtx);
1423 ret = 0;
1424 }
1425 if (ret >= 0) {
1426 ret = frame_finished;
1427 }
1428 }
1429 if (!packet->data && !frame_finished)
1430 {
1431 ret = -1;
1432 }
1433 #else
1434 int used = avcodec_decode_audio4(aCodecCtx, audio_frame, &frame_finished, packet);
1435 #endif
1436
1437 if (frame_finished) {
1438
1439 // determine how many samples were decoded
1440 int plane_size = -1;
1441 data_size = av_samples_get_buffer_size(&plane_size,
1442 AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels,
1443 audio_frame->nb_samples,
1444 (AVSampleFormat) (AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx)), 1);
1445
1446 // Calculate total number of samples
1447 packet_samples = audio_frame->nb_samples * AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
1448 }
1449
1450 // Estimate the # of samples and the end of this packet's location (to prevent GAPS for the next timestamp)
1451 int pts_remaining_samples = packet_samples / info.channels; // Adjust for zero based array
1452
1453 // DEBUG (FOR AUDIO ISSUES) - Get the audio packet start time (in seconds)
1454 int64_t adjusted_pts = packet->pts + audio_pts_offset;
1455 double audio_seconds = double(adjusted_pts) * info.audio_timebase.ToDouble();
1456 double sample_seconds = double(pts_total) / info.sample_rate;
1457
1458 // Debug output
1459 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Decode Info A)", "pts_counter", pts_counter, "PTS", adjusted_pts, "Offset", audio_pts_offset, "PTS Diff", adjusted_pts - prev_pts, "Samples", pts_remaining_samples, "Sample PTS ratio", float(adjusted_pts - prev_pts) / pts_remaining_samples);
1460 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (Decode Info B)", "Sample Diff", pts_remaining_samples - prev_samples - prev_pts, "Total", pts_total, "PTS Seconds", audio_seconds, "Sample Seconds", sample_seconds, "Seconds Diff", audio_seconds - sample_seconds, "raw samples", packet_samples);
1461
1462 // DEBUG (FOR AUDIO ISSUES)
1463 prev_pts = adjusted_pts;
1464 pts_total += pts_remaining_samples;
1465 pts_counter++;
1466 prev_samples = pts_remaining_samples;
1467
1468 // Add audio frame to list of processing audio frames
1469 {
1470 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1471 processing_audio_frames.insert(std::pair<int, int>(previous_packet_location.frame, previous_packet_location.frame));
1472 }
1473
1474 while (pts_remaining_samples) {
1475 // Get Samples per frame (for this frame number)
1476 int samples_per_frame = Frame::GetSamplesPerFrame(previous_packet_location.frame, info.fps, info.sample_rate, info.channels);
1477
1478 // Calculate # of samples to add to this frame
1479 int samples = samples_per_frame - previous_packet_location.sample_start;
1480 if (samples > pts_remaining_samples)
1481 samples = pts_remaining_samples;
1482
1483 // Decrement remaining samples
1484 pts_remaining_samples -= samples;
1485
1486 if (pts_remaining_samples > 0) {
1487 // next frame
1488 previous_packet_location.frame++;
1489 previous_packet_location.sample_start = 0;
1490
1491 // Add audio frame to list of processing audio frames
1492 {
1493 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1494 processing_audio_frames.insert(std::pair<int, int>(previous_packet_location.frame, previous_packet_location.frame));
1495 }
1496
1497 } else {
1498 // Increment sample start
1499 previous_packet_location.sample_start += samples;
1500 }
1501 }
1502
1503
1504 // Allocate audio buffer
1505 int16_t *audio_buf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE];
1506
1507 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (ReSample)", "packet_samples", packet_samples, "info.channels", info.channels, "info.sample_rate", info.sample_rate, "aCodecCtx->sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), "AV_SAMPLE_FMT_S16", AV_SAMPLE_FMT_S16);
1508
1509 // Create output frame
1510 AVFrame *audio_converted = AV_ALLOCATE_FRAME();
1511 AV_RESET_FRAME(audio_converted);
1512 audio_converted->nb_samples = audio_frame->nb_samples;
1513 av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
1514
1515 SWRCONTEXT *avr = NULL;
1516 int nb_samples = 0;
1517
1518 // setup resample context
1519 avr = SWR_ALLOC();
1520 av_opt_set_int(avr, "in_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
1521 av_opt_set_int(avr, "out_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
1522 av_opt_set_int(avr, "in_sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), 0);
1523 av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1524 av_opt_set_int(avr, "in_sample_rate", info.sample_rate, 0);
1525 av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1526 av_opt_set_int(avr, "in_channels", info.channels, 0);
1527 av_opt_set_int(avr, "out_channels", info.channels, 0);
1528 SWR_INIT(avr);
1529
1530 // Convert audio samples
1531 nb_samples = SWR_CONVERT(avr, // audio resample context
1532 audio_converted->data, // output data pointers
1533 audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
1534 audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
1535 audio_frame->data, // input data pointers
1536 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1537 audio_frame->nb_samples); // number of input samples to convert
1538
1539 // Copy audio samples over original samples
1540 memcpy(audio_buf, audio_converted->data[0], audio_converted->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels);
1541
1542 // Deallocate resample buffer
1543 SWR_CLOSE(avr);
1544 SWR_FREE(&avr);
1545 avr = NULL;
1546
1547 // Free AVFrames
1548 av_free(audio_converted->data[0]);
1549 AV_FREE_FRAME(&audio_converted);
1550
1551 int64_t starting_frame_number = -1;
1552 bool partial_frame = true;
1553 for (int channel_filter = 0; channel_filter < info.channels; channel_filter++) {
1554 // Array of floats (to hold samples for each channel)
1555 starting_frame_number = target_frame;
1556 int channel_buffer_size = packet_samples / info.channels;
1557 float *channel_buffer = new float[channel_buffer_size];
1558
1559 // Init buffer array
1560 for (int z = 0; z < channel_buffer_size; z++)
1561 channel_buffer[z] = 0.0f;
1562
1563 // Loop through all samples and add them to our Frame based on channel.
1564 // Toggle through each channel number, since channel data is stored like (left right left right)
1565 int channel = 0;
1566 int position = 0;
1567 for (int sample = 0; sample < packet_samples; sample++) {
1568 // Only add samples for current channel
1569 if (channel_filter == channel) {
1570 // Add sample (convert from (-32768 to 32768) to (-1.0 to 1.0))
1571 channel_buffer[position] = audio_buf[sample] * (1.0f / (1 << 15));
1572
1573 // Increment audio position
1574 position++;
1575 }
1576
1577 // increment channel (if needed)
1578 if ((channel + 1) < info.channels)
1579 // move to next channel
1580 channel++;
1581 else
1582 // reset channel
1583 channel = 0;
1584 }
1585
1586 // Loop through samples, and add them to the correct frames
1587 int start = starting_sample;
1588 int remaining_samples = channel_buffer_size;
1589 float *iterate_channel_buffer = channel_buffer; // pointer to channel buffer
1590 while (remaining_samples > 0) {
1591 // Get Samples per frame (for this frame number)
1592 int samples_per_frame = Frame::GetSamplesPerFrame(starting_frame_number, info.fps, info.sample_rate, info.channels);
1593
1594 // Calculate # of samples to add to this frame
1595 int samples = samples_per_frame - start;
1596 if (samples > remaining_samples)
1597 samples = remaining_samples;
1598
1599 // Create or get the existing frame object
1600 std::shared_ptr<Frame> f = CreateFrame(starting_frame_number);
1601
1602 // Determine if this frame was "partially" filled in
1603 if (samples_per_frame == start + samples)
1604 partial_frame = false;
1605 else
1606 partial_frame = true;
1607
1608 // Add samples for current channel to the frame.
1609 f->AddAudio(true, channel_filter, start, iterate_channel_buffer, samples, 1.0f);
1610
1611 // Debug output
1612 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (f->AddAudio)", "frame", starting_frame_number, "start", start, "samples", samples, "channel", channel_filter, "partial_frame", partial_frame, "samples_per_frame", samples_per_frame);
1613
1614 // Add or update cache
1615 working_cache.Add(f);
1616
1617 // Decrement remaining samples
1618 remaining_samples -= samples;
1619
1620 // Increment buffer (to next set of samples)
1621 if (remaining_samples > 0)
1622 iterate_channel_buffer += samples;
1623
1624 // Increment frame number
1625 starting_frame_number++;
1626
1627 // Reset starting sample #
1628 start = 0;
1629 }
1630
1631 // clear channel buffer
1632 delete[] channel_buffer;
1633 channel_buffer = NULL;
1634 iterate_channel_buffer = NULL;
1635 }
1636
1637 // Clean up some arrays
1638 delete[] audio_buf;
1639 audio_buf = NULL;
1640
1641 // Remove audio frame from list of processing audio frames
1642 {
1643 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1644 // Update all frames as completed
1645 for (int64_t f = target_frame; f < starting_frame_number; f++) {
1646 // Remove the frame # from the processing list. NOTE: If more than one thread is
1647 // processing this frame, the frame # will be in this list multiple times. We are only
1648 // removing a single instance of it here.
1649 processing_audio_frames.erase(processing_audio_frames.find(f));
1650
1651 // Check and see if this frame is also being processed by another thread
1652 if (processing_audio_frames.count(f) == 0)
1653 // No other thread is processing it. Mark the audio as processed (final)
1654 processed_audio_frames[f] = f;
1655 }
1656
1657 if (target_frame == starting_frame_number) {
1658 // This typically never happens, but just in case, remove the currently processing number
1659 processing_audio_frames.erase(processing_audio_frames.find(target_frame));
1660 }
1661 }
1662
1663 // Free audio frame
1664 AV_FREE_FRAME(&audio_frame);
1665
1666 // Debug output
1667 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (After)", "requested_frame", requested_frame, "starting_frame", target_frame, "end_frame", starting_frame_number - 1);
1668
1669 }
1670
1671
1672 // Seek to a specific frame. This is not always frame accurate, it's more of an estimation on many codecs.
1673 void FFmpegReader::Seek(int64_t requested_frame) {
1674 // Adjust for a requested frame that is too small or too large
1675 if (requested_frame < 1)
1676 requested_frame = 1;
1677 if (requested_frame > info.video_length)
1678 requested_frame = info.video_length;
1679
1680 int processing_video_frames_size = 0;
1681 int processing_audio_frames_size = 0;
1682 {
1683 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1684 processing_video_frames_size = processing_video_frames.size();
1685 processing_audio_frames_size = processing_audio_frames.size();
1686 }
1687
1688 // Debug output
1689 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::Seek", "requested_frame", requested_frame, "seek_count", seek_count, "last_frame", last_frame, "processing_video_frames_size", processing_video_frames_size, "processing_audio_frames_size", processing_audio_frames_size, "video_pts_offset", video_pts_offset);
1690
1691 // Wait for any processing frames to complete
1692 while (processing_video_frames_size + processing_audio_frames_size > 0) {
1693 std::this_thread::sleep_for(std::chrono::milliseconds(3));
1694 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1695 processing_video_frames_size = processing_video_frames.size();
1696 processing_audio_frames_size = processing_audio_frames.size();
1697 }
1698
1699 // Clear working cache (since we are seeking to another location in the file)
1700 working_cache.Clear();
1701 missing_frames.Clear();
1702
1703 // Clear processed lists
1704 {
1705 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1706 processing_audio_frames.clear();
1707 processing_video_frames.clear();
1708 processed_video_frames.clear();
1709 processed_audio_frames.clear();
1710 missing_audio_frames.clear();
1711 missing_video_frames.clear();
1712 missing_audio_frames_source.clear();
1713 missing_video_frames_source.clear();
1714 checked_frames.clear();
1715 }
1716
1717 // Reset the last frame variable
1718 last_frame = 0;
1719 current_video_frame = 0;
1720 largest_frame_processed = 0;
1721 num_checks_since_final = 0;
1722 num_packets_since_video_frame = 0;
1723 has_missing_frames = false;
1724 bool has_audio_override = info.has_audio;
1725 bool has_video_override = info.has_video;
1726
1727 // Increment seek count
1728 seek_count++;
1729
1730 // If seeking near frame 1, we need to close and re-open the file (this is more reliable than seeking)
1731 int buffer_amount = std::max(max_concurrent_frames, 8);
1732 if (requested_frame - buffer_amount < 20) {
1733 // Close and re-open file (basically seeking to frame 1)
1734 Close();
1735 Open();
1736
1737 // Update overrides (since closing and re-opening might update these)
1738 info.has_audio = has_audio_override;
1739 info.has_video = has_video_override;
1740
1741 // Not actually seeking, so clear these flags
1742 is_seeking = false;
1743 if (seek_count == 1) {
1744 // Don't redefine this on multiple seek attempts for a specific frame
1745 seeking_frame = 1;
1746 seeking_pts = ConvertFrameToVideoPTS(1);
1747 }
1748 seek_audio_frame_found = 0; // used to detect which frames to throw away after a seek
1749 seek_video_frame_found = 0; // used to detect which frames to throw away after a seek
1750
1751 } else {
1752 // Seek to nearest key-frame (aka, i-frame)
1753 bool seek_worked = false;
1754 int64_t seek_target = 0;
1755
1756 // Seek video stream (if any), except album arts
1757 if (!seek_worked && info.has_video && !HasAlbumArt()) {
1758 seek_target = ConvertFrameToVideoPTS(requested_frame - buffer_amount);
1759 if (av_seek_frame(pFormatCtx, info.video_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) {
1760 fprintf(stderr, "%s: error while seeking video stream\n", pFormatCtx->AV_FILENAME);
1761 } else {
1762 // VIDEO SEEK
1763 is_video_seek = true;
1764 seek_worked = true;
1765 }
1766 }
1767
1768 // Seek audio stream (if not already seeked... and if an audio stream is found)
1769 if (!seek_worked && info.has_audio) {
1770 seek_target = ConvertFrameToAudioPTS(requested_frame - buffer_amount);
1771 if (av_seek_frame(pFormatCtx, info.audio_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) {
1772 fprintf(stderr, "%s: error while seeking audio stream\n", pFormatCtx->AV_FILENAME);
1773 } else {
1774 // AUDIO SEEK
1775 is_video_seek = false;
1776 seek_worked = true;
1777 }
1778 }
1779
1780 // Was the seek successful?
1781 if (seek_worked) {
1782 // Flush audio buffer
1783 if (info.has_audio)
1784 avcodec_flush_buffers(aCodecCtx);
1785
1786 // Flush video buffer
1787 if (info.has_video)
1788 avcodec_flush_buffers(pCodecCtx);
1789
1790 // Reset previous audio location to zero
1791 previous_packet_location.frame = -1;
1792 previous_packet_location.sample_start = 0;
1793
1794 // init seek flags
1795 is_seeking = true;
1796 if (seek_count == 1) {
1797 // Don't redefine this on multiple seek attempts for a specific frame
1798 seeking_pts = seek_target;
1799 seeking_frame = requested_frame;
1800 }
1801 seek_audio_frame_found = 0; // used to detect which frames to throw away after a seek
1802 seek_video_frame_found = 0; // used to detect which frames to throw away after a seek
1803
1804 } else {
1805 // seek failed
1806 is_seeking = false;
1807 seeking_pts = 0;
1808 seeking_frame = 0;
1809
1810 // dislable seeking for this reader (since it failed)
1811 // TODO: Find a safer way to do this... not sure how common it is for a seek to fail.
1812 enable_seek = false;
1813
1814 // Close and re-open file (basically seeking to frame 1)
1815 Close();
1816 Open();
1817
1818 // Update overrides (since closing and re-opening might update these)
1819 info.has_audio = has_audio_override;
1820 info.has_video = has_video_override;
1821 }
1822 }
1823 }
1824
1825 // Get the PTS for the current video packet
1826 int64_t FFmpegReader::GetVideoPTS() {
1827 int64_t current_pts = 0;
1828 if (packet->dts != AV_NOPTS_VALUE)
1829 current_pts = packet->dts;
1830
1831 // Return adjusted PTS
1832 return current_pts;
1833 }
1834
1835 // Update PTS Offset (if any)
1836 void FFmpegReader::UpdatePTSOffset(bool is_video) {
1837 // Determine the offset between the PTS and Frame number (only for 1st frame)
1838 if (is_video) {
1839 // VIDEO PACKET
1840 if (video_pts_offset == 99999) // Has the offset been set yet?
1841 {
1842 // Find the difference between PTS and frame number
1843 video_pts_offset = 0 - GetVideoPTS();
1844
1845 // Find the difference between PTS and frame number
1846 // Also, determine if PTS is invalid (too far away from zero)
1847 // We compare the PTS to the timebase value equal to 1 second (which means the PTS
1848 // must be within the -1 second to +1 second of zero, otherwise we ignore it)
1849 // TODO: Please see https://github.com/OpenShot/libopenshot/pull/565#issuecomment-690985272
1850 // for ideas to improve this logic.
1851 int64_t max_offset = info.video_timebase.Reciprocal().ToFloat();
1852 if (video_pts_offset < -max_offset || video_pts_offset > max_offset) {
1853 // Ignore PTS, it seems invalid
1854 video_pts_offset = 0;
1855 }
1856
1857 // debug output
1858 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdatePTSOffset (Video)", "video_pts_offset", video_pts_offset, "is_video", is_video);
1859 }
1860 } else {
1861 // AUDIO PACKET
1862 if (audio_pts_offset == 99999) // Has the offset been set yet?
1863 {
1864 // Find the difference between PTS and frame number
1865 // Also, determine if PTS is invalid (too far away from zero)
1866 // We compare the PTS to the timebase value equal to 1 second (which means the PTS
1867 // must be within the -1 second to +1 second of zero, otherwise we ignore it)
1868 // TODO: Please see https://github.com/OpenShot/libopenshot/pull/565#issuecomment-690985272
1869 // for ideas to improve this logic.
1870 audio_pts_offset = 0 - packet->pts;
1871 int64_t max_offset = info.audio_timebase.Reciprocal().ToFloat();
1872 if (audio_pts_offset < -max_offset || audio_pts_offset > max_offset) {
1873 // Ignore PTS, it seems invalid
1874 audio_pts_offset = 0;
1875 }
1876
1877 // debug output
1878 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdatePTSOffset (Audio)", "audio_pts_offset", audio_pts_offset, "is_video", is_video);
1879 }
1880 }
1881 }
1882
1883 // Convert PTS into Frame Number
1884 int64_t FFmpegReader::ConvertVideoPTStoFrame(int64_t pts) {
1885 // Apply PTS offset
1886 pts = pts + video_pts_offset;
1887 int64_t previous_video_frame = current_video_frame;
1888
1889 // Get the video packet start time (in seconds)
1890 double video_seconds = double(pts) * info.video_timebase.ToDouble();
1891
1892 // Divide by the video timebase, to get the video frame number (frame # is decimal at this point)
1893 int64_t frame = round(video_seconds * info.fps.ToDouble()) + 1;
1894
1895 // Keep track of the expected video frame #
1896 if (current_video_frame == 0)
1897 current_video_frame = frame;
1898 else {
1899
1900 // Sometimes frames are duplicated due to identical (or similar) timestamps
1901 if (frame == previous_video_frame) {
1902 // return -1 frame number
1903 frame = -1;
1904 } else {
1905 // Increment expected frame
1906 current_video_frame++;
1907 }
1908
1909 if (current_video_frame < frame)
1910 // has missing frames
1911 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ConvertVideoPTStoFrame (detected missing frame)", "calculated frame", frame, "previous_video_frame", previous_video_frame, "current_video_frame", current_video_frame);
1912
1913 // Sometimes frames are missing due to varying timestamps, or they were dropped. Determine
1914 // if we are missing a video frame.
1915 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
1916 while (current_video_frame < frame) {
1917 if (!missing_video_frames.count(current_video_frame)) {
1918 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ConvertVideoPTStoFrame (tracking missing frame)", "current_video_frame", current_video_frame, "previous_video_frame", previous_video_frame);
1919 missing_video_frames.insert(std::pair<int64_t, int64_t>(current_video_frame, previous_video_frame));
1920 missing_video_frames_source.insert(std::pair<int64_t, int64_t>(previous_video_frame, current_video_frame));
1921 }
1922
1923 // Mark this reader as containing missing frames
1924 has_missing_frames = true;
1925
1926 // Increment current frame
1927 current_video_frame++;
1928 }
1929 }
1930
1931 // Return frame #
1932 return frame;
1933 }
1934
1935 // Convert Frame Number into Video PTS
1936 int64_t FFmpegReader::ConvertFrameToVideoPTS(int64_t frame_number) {
1937 // Get timestamp of this frame (in seconds)
1938 double seconds = double(frame_number) / info.fps.ToDouble();
1939
1940 // Calculate the # of video packets in this timestamp
1941 int64_t video_pts = round(seconds / info.video_timebase.ToDouble());
1942
1943 // Apply PTS offset (opposite)
1944 return video_pts - video_pts_offset;
1945 }
1946
1947 // Convert Frame Number into Video PTS
1948 int64_t FFmpegReader::ConvertFrameToAudioPTS(int64_t frame_number) {
1949 // Get timestamp of this frame (in seconds)
1950 double seconds = double(frame_number) / info.fps.ToDouble();
1951
1952 // Calculate the # of audio packets in this timestamp
1953 int64_t audio_pts = round(seconds / info.audio_timebase.ToDouble());
1954
1955 // Apply PTS offset (opposite)
1956 return audio_pts - audio_pts_offset;
1957 }
1958
1959 // Calculate Starting video frame and sample # for an audio PTS
1960 AudioLocation FFmpegReader::GetAudioPTSLocation(int64_t pts) {
1961 // Apply PTS offset
1962 pts = pts + audio_pts_offset;
1963
1964 // Get the audio packet start time (in seconds)
1965 double audio_seconds = double(pts) * info.audio_timebase.ToDouble();
1966
1967 // Divide by the video timebase, to get the video frame number (frame # is decimal at this point)
1968 double frame = (audio_seconds * info.fps.ToDouble()) + 1;
1969
1970 // Frame # as a whole number (no more decimals)
1971 int64_t whole_frame = int64_t(frame);
1972
1973 // Remove the whole number, and only get the decimal of the frame
1974 double sample_start_percentage = frame - double(whole_frame);
1975
1976 // Get Samples per frame
1977 int samples_per_frame = Frame::GetSamplesPerFrame(whole_frame, info.fps, info.sample_rate, info.channels);
1978
1979 // Calculate the sample # to start on
1980 int sample_start = round(double(samples_per_frame) * sample_start_percentage);
1981
1982 // Protect against broken (i.e. negative) timestamps
1983 if (whole_frame < 1)
1984 whole_frame = 1;
1985 if (sample_start < 0)
1986 sample_start = 0;
1987
1988 // Prepare final audio packet location
1989 AudioLocation location = {whole_frame, sample_start};
1990
1991 // Compare to previous audio packet (and fix small gaps due to varying PTS timestamps)
1992 if (previous_packet_location.frame != -1) {
1993 if (location.is_near(previous_packet_location, samples_per_frame, samples_per_frame)) {
1994 int64_t orig_frame = location.frame;
1995 int orig_start = location.sample_start;
1996
1997 // Update sample start, to prevent gaps in audio
1998 location.sample_start = previous_packet_location.sample_start;
1999 location.frame = previous_packet_location.frame;
2000
2001 // Debug output
2002 ZmqLogger::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);
2003
2004 } else {
2005 // Debug output
2006 ZmqLogger::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);
2007
2008 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2009 for (int64_t audio_frame = previous_packet_location.frame; audio_frame < location.frame; audio_frame++) {
2010 if (!missing_audio_frames.count(audio_frame)) {
2011 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAudioPTSLocation (tracking missing frame)", "missing_audio_frame", audio_frame, "previous_audio_frame", previous_packet_location.frame, "new location frame", location.frame);
2012 missing_audio_frames.insert(std::pair<int64_t, int64_t>(audio_frame, previous_packet_location.frame - 1));
2013 }
2014 }
2015 }
2016 }
2017
2018 // Set previous location
2019 previous_packet_location = location;
2020
2021 // Return the associated video frame and starting sample #
2022 return location;
2023 }
2024
2025 // Create a new Frame (or return an existing one) and add it to the working queue.
2026 std::shared_ptr<Frame> FFmpegReader::CreateFrame(int64_t requested_frame) {
2027 // Check working cache
2028 std::shared_ptr<Frame> output = working_cache.GetFrame(requested_frame);
2029
2030 if (!output) {
2031 // Lock
2032 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2033
2034 // (re-)Check working cache
2035 output = working_cache.GetFrame(requested_frame);
2036 if(output) return output;
2037
2038 // Create a new frame on the working cache
2039 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);
2040 output->SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den); // update pixel ratio
2041 output->ChannelsLayout(info.channel_layout); // update audio channel layout from the parent reader
2042 output->SampleRate(info.sample_rate); // update the frame's sample rate of the parent reader
2043
2044 working_cache.Add(output);
2045
2046 // Set the largest processed frame (if this is larger)
2047 if (requested_frame > largest_frame_processed)
2048 largest_frame_processed = requested_frame;
2049 }
2050 // Return frame
2051 return output;
2052 }
2053
2054 // Determine if frame is partial due to seek
2055 bool FFmpegReader::IsPartialFrame(int64_t requested_frame) {
2056
2057 // Sometimes a seek gets partial frames, and we need to remove them
2058 bool seek_trash = false;
2059 int64_t max_seeked_frame = seek_audio_frame_found; // determine max seeked frame
2060 if (seek_video_frame_found > max_seeked_frame) {
2061 max_seeked_frame = seek_video_frame_found;
2062 }
2063 if ((info.has_audio && seek_audio_frame_found && max_seeked_frame >= requested_frame) ||
2064 (info.has_video && seek_video_frame_found && max_seeked_frame >= requested_frame)) {
2065 seek_trash = true;
2066 }
2067
2068 return seek_trash;
2069 }
2070
2071 // Check if a frame is missing and attempt to replace its frame image (and
2072 bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) {
2073 // Lock
2074 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2075
2076 // Increment check count for this frame (or init to 1)
2077 ++checked_frames[requested_frame];
2078
2079 // Debug output
2080 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame", "requested_frame", requested_frame, "has_missing_frames", has_missing_frames, "missing_video_frames.size()", missing_video_frames.size(), "checked_count", checked_frames[requested_frame]);
2081
2082 // Missing frames (sometimes frame #'s are skipped due to invalid or missing timestamps)
2083 std::map<int64_t, int64_t>::iterator itr;
2084 bool found_missing_frame = false;
2085
2086 // Special MP3 Handling (ignore more than 1 video frame)
2087 if (info.has_audio and info.has_video) {
2088 // If MP3 with single video frame, handle this special case by copying the previously
2089 // decoded image to the new frame. Otherwise, it will spend a huge amount of
2090 // CPU time looking for missing images for all the audio-only frames.
2091 if (checked_frames[requested_frame] > 8 && !missing_video_frames.count(requested_frame) &&
2092 !processing_audio_frames.count(requested_frame) && processed_audio_frames.count(requested_frame) &&
2093 last_video_frame && last_video_frame->has_image_data && HasAlbumArt()) {
2094 missing_video_frames.insert(std::pair<int64_t, int64_t>(requested_frame, last_video_frame->number));
2095 missing_video_frames_source.insert(std::pair<int64_t, int64_t>(last_video_frame->number, requested_frame));
2096 missing_frames.Add(last_video_frame);
2097 }
2098 }
2099
2100 // Check if requested video frame is a missing
2101 if (missing_video_frames.count(requested_frame)) {
2102 int64_t missing_source_frame = missing_video_frames.find(requested_frame)->second;
2103
2104 // Increment missing source frame check count (or init to 1)
2105 ++checked_frames[missing_source_frame];
2106
2107 // Get the previous frame of this missing frame (if it's available in missing cache)
2108 std::shared_ptr<Frame> parent_frame = missing_frames.GetFrame(missing_source_frame);
2109 if (parent_frame == NULL) {
2110 parent_frame = final_cache.GetFrame(missing_source_frame);
2111 if (parent_frame != NULL) {
2112 // Add missing final frame to missing cache
2113 missing_frames.Add(parent_frame);
2114 }
2115 }
2116
2117 // Create blank missing frame
2118 std::shared_ptr<Frame> missing_frame = CreateFrame(requested_frame);
2119
2120 // Debug output
2121 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame (Is Previous Video Frame Final)", "requested_frame", requested_frame, "missing_frame->number", missing_frame->number, "missing_source_frame", missing_source_frame);
2122
2123 // If previous frame found, copy image from previous to missing frame (else we'll just wait a bit and try again later)
2124 if (parent_frame != NULL) {
2125 // Debug output
2126 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame (AddImage from Previous Video Frame)", "requested_frame", requested_frame, "missing_frame->number", missing_frame->number, "missing_source_frame", missing_source_frame);
2127
2128 // Add this frame to the processed map (since it's already done)
2129 std::shared_ptr<QImage> parent_image = parent_frame->GetImage();
2130 if (parent_image) {
2131 missing_frame->AddImage(std::make_shared<QImage>(*parent_image));
2132 processed_video_frames[missing_frame->number] = missing_frame->number;
2133 }
2134 }
2135 }
2136
2137 // Check if requested audio frame is a missing
2138 if (missing_audio_frames.count(requested_frame)) {
2139
2140 // Create blank missing frame
2141 std::shared_ptr<Frame> missing_frame = CreateFrame(requested_frame);
2142
2143 // Get Samples per frame (for this frame number)
2144 int samples_per_frame = Frame::GetSamplesPerFrame(missing_frame->number, info.fps, info.sample_rate, info.channels);
2145
2146 // Debug output
2147 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame (Add Silence for Missing Audio Frame)", "requested_frame", requested_frame, "missing_frame->number", missing_frame->number, "samples_per_frame", samples_per_frame);
2148
2149 // Add this frame to the processed map (since it's already done)
2150 missing_frame->AddAudioSilence(samples_per_frame);
2151 processed_audio_frames[missing_frame->number] = missing_frame->number;
2152 }
2153
2154 return found_missing_frame;
2155 }
2156
2157 // Check the working queue, and move finished frames to the finished queue
2158 void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_frame) {
2159 // Loop through all working queue frames
2160 bool checked_count_tripped = false;
2161 int max_checked_count = 80;
2162
2163 // Check if requested frame is 'missing'
2164 CheckMissingFrame(requested_frame);
2165
2166 while (true) {
2167 // Get the front frame of working cache
2168 std::shared_ptr<Frame> f(working_cache.GetSmallestFrame());
2169
2170 // Was a frame found?
2171 if (!f)
2172 // No frames found
2173 break;
2174
2175 // Remove frames which are too old
2176 if (f->number < (requested_frame - (max_concurrent_frames * 2))) {
2177 working_cache.Remove(f->number);
2178 }
2179
2180 // Check if this frame is 'missing'
2181 CheckMissingFrame(f->number);
2182
2183 // Init # of times this frame has been checked so far
2184 int checked_count = 0;
2185 int checked_frames_size = 0;
2186
2187 bool is_video_ready = false;
2188 bool is_audio_ready = false;
2189 { // limit scope of next few lines
2190 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2191 is_video_ready = processed_video_frames.count(f->number);
2192 is_audio_ready = processed_audio_frames.count(f->number);
2193
2194 // Get check count for this frame
2195 checked_frames_size = checked_frames.size();
2196 if (!checked_count_tripped || f->number >= requested_frame)
2197 checked_count = checked_frames[f->number];
2198 else
2199 // Force checked count over the limit
2200 checked_count = max_checked_count;
2201 }
2202
2203 if (previous_packet_location.frame == f->number && !end_of_stream)
2204 is_audio_ready = false; // don't finalize the last processed audio frame
2205 bool is_seek_trash = IsPartialFrame(f->number);
2206
2207 // Adjust for available streams
2208 if (!info.has_video) is_video_ready = true;
2209 if (!info.has_audio) is_audio_ready = true;
2210
2211 // Make final any frames that get stuck (for whatever reason)
2212 if (checked_count >= max_checked_count && (!is_video_ready || !is_audio_ready)) {
2213 // Debug output
2214 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (exceeded checked_count)", "requested_frame", requested_frame, "frame_number", f->number, "is_video_ready", is_video_ready, "is_audio_ready", is_audio_ready, "checked_count", checked_count, "checked_frames_size", checked_frames_size);
2215
2216 // Trigger checked count tripped mode (clear out all frames before requested frame)
2217 checked_count_tripped = true;
2218
2219 if (info.has_video && !is_video_ready && last_video_frame) {
2220 // Copy image from last frame
2221 f->AddImage(std::make_shared<QImage>(*last_video_frame->GetImage()));
2222 is_video_ready = true;
2223 }
2224
2225 if (info.has_audio && !is_audio_ready) {
2226 // Mark audio as processed, and indicate the frame has audio data
2227 is_audio_ready = true;
2228 }
2229 }
2230
2231 // Debug output
2232 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames", "requested_frame", requested_frame, "frame_number", f->number, "is_video_ready", is_video_ready, "is_audio_ready", is_audio_ready, "checked_count", checked_count, "checked_frames_size", checked_frames_size);
2233
2234 // Check if working frame is final
2235 if ((!end_of_stream && is_video_ready && is_audio_ready) || end_of_stream || is_seek_trash) {
2236 // Debug output
2237 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (mark frame as final)", "requested_frame", requested_frame, "f->number", f->number, "is_seek_trash", is_seek_trash, "Working Cache Count", working_cache.Count(), "Final Cache Count", final_cache.Count(), "end_of_stream", end_of_stream);
2238
2239 if (!is_seek_trash) {
2240 // Add missing image (if needed - sometimes end_of_stream causes frames with only audio)
2241 if (info.has_video && !is_video_ready && last_video_frame)
2242 // Copy image from last frame
2243 f->AddImage(std::make_shared<QImage>(*last_video_frame->GetImage()));
2244
2245 // Reset counter since last 'final' frame
2246 num_checks_since_final = 0;
2247
2248 // Move frame to final cache
2249 final_cache.Add(f);
2250
2251 // Add to missing cache (if another frame depends on it)
2252 {
2253 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2254 if (missing_video_frames_source.count(f->number)) {
2255 // Debug output
2256 ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckWorkingFrames (add frame to missing cache)", "f->number", f->number, "is_seek_trash", is_seek_trash, "Missing Cache Count", missing_frames.Count(), "Working Cache Count", working_cache.Count(), "Final Cache Count", final_cache.Count());
2257 missing_frames.Add(f);
2258 }
2259
2260 // Remove from 'checked' count
2261 checked_frames.erase(f->number);
2262 }
2263
2264 // Remove frame from working cache
2265 working_cache.Remove(f->number);
2266
2267 // Update last frame processed
2268 last_frame = f->number;
2269
2270 } else {
2271 // Seek trash, so delete the frame from the working cache, and never add it to the final cache.
2272 working_cache.Remove(f->number);
2273 }
2274
2275 } else {
2276 // Stop looping
2277 break;
2278 }
2279 }
2280 }
2281
2282 // Check for the correct frames per second (FPS) value by scanning the 1st few seconds of video packets.
2283 void FFmpegReader::CheckFPS() {
2284 check_fps = true;
2285
2286
2287 int first_second_counter = 0;
2288 int second_second_counter = 0;
2289 int third_second_counter = 0;
2290 int forth_second_counter = 0;
2291 int fifth_second_counter = 0;
2292 int frames_detected = 0;
2293 int64_t pts = 0;
2294
2295 // Loop through the stream
2296 while (true) {
2297 // Get the next packet (if any)
2298 if (GetNextPacket() < 0)
2299 // Break loop when no more packets found
2300 break;
2301
2302 // Video packet
2303 if (packet->stream_index == videoStream) {
2304 // Check if the AVFrame is finished and set it
2305 if (GetAVFrame()) {
2306 // Update PTS / Frame Offset (if any)
2307 UpdatePTSOffset(true);
2308
2309 // Get PTS of this packet
2310 pts = GetVideoPTS();
2311
2312 // Remove pFrame
2313 RemoveAVFrame(pFrame);
2314
2315 // Apply PTS offset
2316 pts += video_pts_offset;
2317
2318 // Get the video packet start time (in seconds)
2319 double video_seconds = double(pts) * info.video_timebase.ToDouble();
2320
2321 // Increment the correct counter
2322 if (video_seconds <= 1.0)
2323 first_second_counter++;
2324 else if (video_seconds > 1.0 && video_seconds <= 2.0)
2325 second_second_counter++;
2326 else if (video_seconds > 2.0 && video_seconds <= 3.0)
2327 third_second_counter++;
2328 else if (video_seconds > 3.0 && video_seconds <= 4.0)
2329 forth_second_counter++;
2330 else if (video_seconds > 4.0 && video_seconds <= 5.0)
2331 fifth_second_counter++;
2332
2333 // Increment counters
2334 frames_detected++;
2335 }
2336 }
2337 }
2338
2339 // Double check that all counters have greater than zero (or give up)
2340 if (second_second_counter != 0 && third_second_counter != 0 && forth_second_counter != 0 && fifth_second_counter != 0) {
2341 // Calculate average FPS (average of first few seconds)
2342 int sum_fps = second_second_counter + third_second_counter + forth_second_counter + fifth_second_counter;
2343 int avg_fps = round(sum_fps / 4.0f);
2344
2345 // Update FPS
2346 info.fps = Fraction(avg_fps, 1);
2347
2348 // Update Duration and Length
2349 info.video_length = frames_detected;
2350 info.duration = frames_detected / (sum_fps / 4.0f);
2351
2352 // Update video bit rate
2353 info.video_bit_rate = info.file_size / info.duration;
2354 } else if (second_second_counter != 0 && third_second_counter != 0) {
2355 // Calculate average FPS (only on second 2)
2356 int sum_fps = second_second_counter;
2357
2358 // Update FPS
2359 info.fps = Fraction(sum_fps, 1);
2360
2361 // Update Duration and Length
2362 info.video_length = frames_detected;
2363 info.duration = frames_detected / float(sum_fps);
2364
2365 // Update video bit rate
2366 info.video_bit_rate = info.file_size / info.duration;
2367 } else {
2368 // Too short to determine framerate, just default FPS
2369 // Set a few important default video settings (so audio can be divided into frames)
2370 info.fps.num = 30;
2371 info.fps.den = 1;
2372
2373 // Calculate number of frames
2374 info.video_length = frames_detected;
2375 info.duration = frames_detected / info.fps.ToFloat();
2376 }
2377 }
2378
2379 // Remove AVFrame from cache (and deallocate its memory)
2380 void FFmpegReader::RemoveAVFrame(AVFrame *remove_frame) {
2381 // Remove pFrame (if exists)
2382 if (remove_frame) {
2383 // Free memory
2384 av_freep(&remove_frame->data[0]);
2385 #ifndef WIN32
2386 AV_FREE_FRAME(&remove_frame);
2387 #endif
2388 }
2389 }
2390
2391 // Remove AVPacket from cache (and deallocate its memory)
2392 void FFmpegReader::RemoveAVPacket(AVPacket *remove_packet) {
2393 // deallocate memory for packet
2394 AV_FREE_PACKET(remove_packet);
2395
2396 // Delete the object
2397 delete remove_packet;
2398 }
2399
2400 /// Get the smallest video frame that is still being processed
2401 int64_t FFmpegReader::GetSmallestVideoFrame() {
2402 // Loop through frame numbers
2403 std::map<int64_t, int64_t>::iterator itr;
2404 int64_t smallest_frame = -1;
2405 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2406 for (itr = processing_video_frames.begin(); itr != processing_video_frames.end(); ++itr) {
2407 if (itr->first < smallest_frame || smallest_frame == -1)
2408 smallest_frame = itr->first;
2409 }
2410
2411 // Return frame number
2412 return smallest_frame;
2413 }
2414
2415 /// Get the smallest audio frame that is still being processed
2416 int64_t FFmpegReader::GetSmallestAudioFrame() {
2417 // Loop through frame numbers
2418 std::map<int64_t, int64_t>::iterator itr;
2419 int64_t smallest_frame = -1;
2420 const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
2421 for (itr = processing_audio_frames.begin(); itr != processing_audio_frames.end(); ++itr) {
2422 if (itr->first < smallest_frame || smallest_frame == -1)
2423 smallest_frame = itr->first;
2424 }
2425
2426 // Return frame number
2427 return smallest_frame;
2428 }
2429
2430 // Generate JSON string of this object
2431 std::string FFmpegReader::Json() const {
2432
2433 // Return formatted string
2434 return JsonValue().toStyledString();
2435 }
2436
2437 // Generate Json::Value for this object
2438 Json::Value FFmpegReader::JsonValue() const {
2439
2440 // Create root json object
2441 Json::Value root = ReaderBase::JsonValue(); // get parent properties
2442 root["type"] = "FFmpegReader";
2443 root["path"] = path;
2444
2445 // return JsonValue
2446 return root;
2447 }
2448
2449 // Load JSON string into this object
2450 void FFmpegReader::SetJson(const std::string value) {
2451
2452 // Parse JSON string into JSON objects
2453 try {
2454 const Json::Value root = openshot::stringToJson(value);
2455 // Set all values that match
2456 SetJsonValue(root);
2457 }
2458 catch (const std::exception& e) {
2459 // Error parsing JSON (or missing keys)
2460 throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
2461 }
2462 }
2463
2464 // Load Json::Value into this object
2465 void FFmpegReader::SetJsonValue(const Json::Value root) {
2466
2467 // Set parent data
2468 ReaderBase::SetJsonValue(root);
2469
2470 // Set data from Json (if key is found)
2471 if (!root["path"].isNull())
2472 path = root["path"].asString();
2473
2474 // Re-Open path, and re-init everything (if needed)
2475 if (is_open) {
2476 Close();
2477 Open();
2478 }
2479 }
2480