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