OpenShot Library | libopenshot  0.2.2
FFmpegWriter.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for FFmpegWriter class
4  * @author Jonathan Thomas <jonathan@openshot.org>, Fabrice Bellard
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2013 OpenShot Studios, LLC, Fabrice Bellard
9  * (http://www.openshotstudios.com). This file is part of
10  * OpenShot Library (http://www.openshot.org), an open-source project
11  * dedicated to delivering high quality video editing and animation solutions
12  * to the world.
13  *
14  * This file is originally based on the Libavformat API example, and then modified
15  * by the libopenshot project.
16  *
17  * OpenShot Library (libopenshot) is free software: you can redistribute it
18  * and/or modify it under the terms of the GNU Lesser General Public License
19  * as published by the Free Software Foundation, either version 3 of the
20  * License, or (at your option) any later version.
21  *
22  * OpenShot Library (libopenshot) is distributed in the hope that it will be
23  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public License
28  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #include "../include/FFmpegWriter.h"
32 
33 using namespace openshot;
34 
36  path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL),
37  audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
38  initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32),
39  rescaler_position(0), video_codec(NULL), audio_codec(NULL), is_writing(false), write_video_count(0), write_audio_count(0),
40  original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
41  write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL)
42 {
43 
44  // Disable audio & video (so they can be independently enabled)
45  info.has_audio = false;
46  info.has_video = false;
47 
48  // Initialize FFMpeg, and register all formats and codecs
50 
51  // auto detect format
52  auto_detect_format();
53 }
54 
55 // Open the writer
57 {
58  // Open the writer
59  is_open = true;
60 
61  // Prepare streams (if needed)
62  if (!prepare_streams)
64 
65  // Write header (if needed)
66  if (!write_header)
67  WriteHeader();
68 }
69 
70 // auto detect format (from path)
71 void FFmpegWriter::auto_detect_format()
72 {
73  // Auto detect the output format from the name. default is mpeg.
74  fmt = av_guess_format(NULL, path.c_str(), NULL);
75  if (!fmt)
76  throw InvalidFormat("Could not deduce output format from file extension.", path);
77 
78  // Allocate the output media context
79  AV_OUTPUT_CONTEXT(&oc, path.c_str());
80  if (!oc)
81  throw OutOfMemory("Could not allocate memory for AVFormatContext.", path);
82 
83  // Set the AVOutputFormat for the current AVFormatContext
84  oc->oformat = fmt;
85 
86  // Update codec names
87  if (fmt->video_codec != AV_CODEC_ID_NONE && info.has_video)
88  // Update video codec name
89  info.vcodec = avcodec_find_encoder(fmt->video_codec)->name;
90 
91  if (fmt->audio_codec != AV_CODEC_ID_NONE && info.has_audio)
92  // Update audio codec name
93  info.acodec = avcodec_find_encoder(fmt->audio_codec)->name;
94 }
95 
96 // initialize streams
97 void FFmpegWriter::initialize_streams()
98 {
99  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::initialize_streams", "fmt->video_codec", fmt->video_codec, "fmt->audio_codec", fmt->audio_codec, "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE, "", -1, "", -1, "", -1);
100 
101  // Add the audio and video streams using the default format codecs and initialize the codecs
102  video_st = NULL;
103  audio_st = NULL;
104  if (fmt->video_codec != AV_CODEC_ID_NONE && info.has_video)
105  // Add video stream
106  video_st = add_video_stream();
107 
108  if (fmt->audio_codec != AV_CODEC_ID_NONE && info.has_audio)
109  // Add audio stream
110  audio_st = add_audio_stream();
111 }
112 
113 // Set video export options
114 void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
115 {
116  // Set the video options
117  if (codec.length() > 0)
118  {
119  AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
120  if (new_codec == NULL)
121  throw InvalidCodec("A valid video codec could not be found for this file.", path);
122  else {
123  // Set video codec
124  info.vcodec = new_codec->name;
125 
126  // Update video codec in fmt
127  fmt->video_codec = new_codec->id;
128  }
129  }
130  if (fps.num > 0)
131  {
132  // Set frames per second (if provided)
133  info.fps.num = fps.num;
134  info.fps.den = fps.den;
135 
136  // Set the timebase (inverse of fps)
139  }
140  if (width >= 1)
141  info.width = width;
142  if (height >= 1)
143  info.height = height;
144  if (pixel_ratio.num > 0)
145  {
146  info.pixel_ratio.num = pixel_ratio.num;
147  info.pixel_ratio.den = pixel_ratio.den;
148  }
149  if (bit_rate >= 1000)
150  info.video_bit_rate = bit_rate;
151 
152  info.interlaced_frame = interlaced;
153  info.top_field_first = top_field_first;
154 
155  // Calculate the DAR (display aspect ratio)
157 
158  // Reduce size fraction
159  size.Reduce();
160 
161  // Set the ratio based on the reduced fraction
162  info.display_ratio.num = size.num;
163  info.display_ratio.den = size.den;
164 
165  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetVideoOptions (" + codec + ")", "width", width, "height", height, "size.num", size.num, "size.den", size.den, "fps.num", fps.num, "fps.den", fps.den);
166 
167  // Enable / Disable video
168  info.has_video = has_video;
169 }
170 
171 // Set audio export options
172 void FFmpegWriter::SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate)
173 {
174  // Set audio options
175  if (codec.length() > 0)
176  {
177  AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
178  if (new_codec == NULL)
179  throw InvalidCodec("A valid audio codec could not be found for this file.", path);
180  else
181  {
182  // Set audio codec
183  info.acodec = new_codec->name;
184 
185  // Update audio codec in fmt
186  fmt->audio_codec = new_codec->id;
187  }
188  }
189  if (sample_rate > 7999)
190  info.sample_rate = sample_rate;
191  if (channels > 0)
192  info.channels = channels;
193  if (bit_rate > 999)
194  info.audio_bit_rate = bit_rate;
195  info.channel_layout = channel_layout;
196 
197  // init resample options (if zero)
198  if (original_sample_rate == 0)
199  original_sample_rate = info.sample_rate;
200  if (original_channels == 0)
201  original_channels = info.channels;
202 
203  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetAudioOptions (" + codec + ")", "sample_rate", sample_rate, "channels", channels, "bit_rate", bit_rate, "", -1, "", -1, "", -1);
204 
205  // Enable / Disable audio
206  info.has_audio = has_audio;
207 }
208 
209 // Set custom options (some codecs accept additional params)
210 void FFmpegWriter::SetOption(StreamType stream, string name, string value)
211 {
212  // Declare codec context
213  AVCodecContext *c = NULL;
214  AVStream *st = NULL;
215  stringstream convert(value);
216 
217  if (info.has_video && stream == VIDEO_STREAM && video_st) {
218  st = video_st;
219  // Get codec context
220  c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec);
221  }
222  else if (info.has_audio && stream == AUDIO_STREAM && audio_st) {
223  st = audio_st;
224  // Get codec context
225  c = AV_GET_CODEC_PAR_CONTEXT(st, audio_codec);
226  }
227  else
228  throw NoStreamsFound("The stream was not found. Be sure to call PrepareStreams() first.", path);
229 
230  // Init AVOption
231  const AVOption *option = NULL;
232 
233  // Was a codec / stream found?
234  if (c)
235  // Find AVOption (if it exists)
236  option = AV_OPTION_FIND(c->priv_data, name.c_str());
237 
238  // Was option found?
239  if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
240  name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate"))
241  {
242  // Check for specific named options
243  if (name == "g")
244  // Set gop_size
245  convert >> c->gop_size;
246 
247  else if (name == "qmin")
248  // Minimum quantizer
249  convert >> c->qmin;
250 
251  else if (name == "qmax")
252  // Maximum quantizer
253  convert >> c->qmax;
254 
255  else if (name == "max_b_frames")
256  // Maximum number of B-frames between non-B-frames
257  convert >> c->max_b_frames;
258 
259  else if (name == "mb_decision")
260  // Macroblock decision mode
261  convert >> c->mb_decision;
262 
263  else if (name == "level")
264  // Set codec level
265  convert >> c->level;
266 
267  else if (name == "profile")
268  // Set codec profile
269  convert >> c->profile;
270 
271  else if (name == "slices")
272  // Indicates number of picture subdivisions
273  convert >> c->slices;
274 
275  else if (name == "rc_min_rate")
276  // Minimum bitrate
277  convert >> c->rc_min_rate;
278 
279  else if (name == "rc_max_rate")
280  // Maximum bitrate
281  convert >> c->rc_max_rate;
282 
283  else if (name == "rc_buffer_size")
284  // Buffer size
285  convert >> c->rc_buffer_size;
286 
287  else
288  // Set AVOption
289  AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
290 
291  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetOption (" + (string)name + ")", "stream == VIDEO_STREAM", stream == VIDEO_STREAM, "", -1, "", -1, "", -1, "", -1, "", -1);
292 
293  }
294  else
295  throw InvalidOptions("The option is not valid for this codec.", path);
296 
297 }
298 
299 /// Determine if codec name is valid
300 bool FFmpegWriter::IsValidCodec(string codec_name) {
301  // Initialize FFMpeg, and register all formats and codecs
303 
304  // Find the codec (if any)
305  if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
306  return false;
307  else
308  return true;
309 }
310 
311 // Prepare & initialize streams and open codecs
313 {
314  if (!info.has_audio && !info.has_video)
315  throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
316 
317  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::PrepareStreams [" + path + "]", "info.has_audio", info.has_audio, "info.has_video", info.has_video, "", -1, "", -1, "", -1, "", -1);
318 
319  // Initialize the streams (i.e. add the streams)
320  initialize_streams();
321 
322  // Now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers
323  if (info.has_video && video_st)
324  open_video(oc, video_st);
325  if (info.has_audio && audio_st)
326  open_audio(oc, audio_st);
327 
328  // Mark as 'prepared'
329  prepare_streams = true;
330 }
331 
332 // Write the file header (after the options are set)
334 {
335  if (!info.has_audio && !info.has_video)
336  throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
337 
338  // Open the output file, if needed
339  if (!(fmt->flags & AVFMT_NOFILE)) {
340  if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
341  throw InvalidFile("Could not open or write file.", path);
342  }
343 
344  // Force the output filename (which doesn't always happen for some reason)
345  snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", path.c_str());
346 
347  // Write the stream header, if any
348  // TODO: add avoptions / parameters instead of NULL
349 
350  // Add general metadata (if any)
351  for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
352  {
353  av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
354  }
355 
356  if (avformat_write_header(oc, NULL) != 0) {
357  throw InvalidFile("Could not write header to file.", path);
358  };
359 
360  // Mark as 'written'
361  write_header = true;
362 
363  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteHeader", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
364 }
365 
366 // Add a frame to the queue waiting to be encoded.
367 void FFmpegWriter::WriteFrame(std::shared_ptr<Frame> frame)
368 {
369  // Check for open reader (or throw exception)
370  if (!is_open)
371  throw WriterClosed("The FFmpegWriter is closed. Call Open() before calling this method.", path);
372 
373  // Add frame pointer to "queue", waiting to be processed the next
374  // time the WriteFrames() method is called.
375  if (info.has_video && video_st)
376  spooled_video_frames.push_back(frame);
377 
378  if (info.has_audio && audio_st)
379  spooled_audio_frames.push_back(frame);
380 
381  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteFrame", "frame->number", frame->number, "spooled_video_frames.size()", spooled_video_frames.size(), "spooled_audio_frames.size()", spooled_audio_frames.size(), "cache_size", cache_size, "is_writing", is_writing, "", -1);
382 
383  // Write the frames once it reaches the correct cache size
384  if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
385  {
386  // Is writer currently writing?
387  if (!is_writing)
388  // Write frames to video file
389  write_queued_frames();
390 
391  else
392  {
393  // Write frames to video file
394  write_queued_frames();
395  }
396  }
397 
398  // Keep track of the last frame added
399  last_frame = frame;
400 }
401 
402 // Write all frames in the queue to the video file.
403 void FFmpegWriter::write_queued_frames()
404 {
405  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_queued_frames", "spooled_video_frames.size()", spooled_video_frames.size(), "spooled_audio_frames.size()", spooled_audio_frames.size(), "", -1, "", -1, "", -1, "", -1);
406 
407  // Flip writing flag
408  is_writing = true;
409 
410  // Transfer spool to queue
411  queued_video_frames = spooled_video_frames;
412  queued_audio_frames = spooled_audio_frames;
413 
414  // Empty spool
415  spooled_video_frames.clear();
416  spooled_audio_frames.clear();
417 
418  // Set the number of threads in OpenMP
419  omp_set_num_threads(OPEN_MP_NUM_PROCESSORS);
420  // Allow nested OpenMP sections
421  omp_set_nested(true);
422 
423  // Create blank exception
424  bool has_error_encoding_video = false;
425 
426  #pragma omp parallel
427  {
428  #pragma omp single
429  {
430  // Process all audio frames (in a separate thread)
431  if (info.has_audio && audio_st && !queued_audio_frames.empty())
432  write_audio_packets(false);
433 
434  // Loop through each queued image frame
435  while (!queued_video_frames.empty())
436  {
437  // Get front frame (from the queue)
438  std::shared_ptr<Frame> frame = queued_video_frames.front();
439 
440  // Add to processed queue
441  processed_frames.push_back(frame);
442 
443  // Encode and add the frame to the output file
444  if (info.has_video && video_st)
445  process_video_packet(frame);
446 
447  // Remove front item
448  queued_video_frames.pop_front();
449 
450  } // end while
451  } // end omp single
452 
453  #pragma omp single
454  {
455  // Loop back through the frames (in order), and write them to the video file
456  while (!processed_frames.empty())
457  {
458  // Get front frame (from the queue)
459  std::shared_ptr<Frame> frame = processed_frames.front();
460 
461  if (info.has_video && video_st)
462  {
463  // Add to deallocate queue (so we can remove the AVFrames when we are done)
464  deallocate_frames.push_back(frame);
465 
466  // Does this frame's AVFrame still exist
467  if (av_frames.count(frame))
468  {
469  // Get AVFrame
470  AVFrame *frame_final = av_frames[frame];
471 
472  // Write frame to video file
473  bool success = write_video_packet(frame, frame_final);
474  if (!success)
475  has_error_encoding_video = true;
476  }
477  }
478 
479  // Remove front item
480  processed_frames.pop_front();
481  }
482 
483  // Loop through, and deallocate AVFrames
484  while (!deallocate_frames.empty())
485  {
486  // Get front frame (from the queue)
487  std::shared_ptr<Frame> frame = deallocate_frames.front();
488 
489  // Does this frame's AVFrame still exist
490  if (av_frames.count(frame))
491  {
492  // Get AVFrame
493  AVFrame *av_frame = av_frames[frame];
494 
495  // Deallocate AVPicture and AVFrame
496  av_freep(&(av_frame->data[0]));
497  AV_FREE_FRAME(&av_frame);
498  av_frames.erase(frame);
499  }
500 
501  // Remove front item
502  deallocate_frames.pop_front();
503  }
504 
505  // Done writing
506  is_writing = false;
507 
508  } // end omp single
509  } // end omp parallel
510 
511  // Raise exception from main thread
512  if (has_error_encoding_video)
513  throw ErrorEncodingVideo("Error while writing raw video frame", -1);
514 }
515 
516 // Write a block of frames from a reader
517 void FFmpegWriter::WriteFrame(ReaderBase* reader, int64_t start, int64_t length)
518 {
519  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteFrame (from Reader)", "start", start, "length", length, "", -1, "", -1, "", -1, "", -1);
520 
521  // Loop through each frame (and encoded it)
522  for (int64_t number = start; number <= length; number++)
523  {
524  // Get the frame
525  std::shared_ptr<Frame> f = reader->GetFrame(number);
526 
527  // Encode frame
528  WriteFrame(f);
529  }
530 }
531 
532 // Write the file trailer (after all frames are written)
534 {
535  // Write any remaining queued frames to video file
536  write_queued_frames();
537 
538  // Process final audio frame (if any)
539  if (info.has_audio && audio_st)
540  write_audio_packets(true);
541 
542  // Flush encoders (who sometimes hold on to frames)
543  flush_encoders();
544 
545  /* write the trailer, if any. The trailer must be written
546  * before you close the CodecContexts open when you wrote the
547  * header; otherwise write_trailer may try to use memory that
548  * was freed on av_codec_close() */
549  av_write_trailer(oc);
550 
551  // Mark as 'written'
552  write_trailer = true;
553 
554  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteTrailer", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
555 }
556 
557 // Flush encoders
558 void FFmpegWriter::flush_encoders()
559 {
560  if (info.has_audio && audio_codec && AV_GET_CODEC_TYPE(audio_st) == AVMEDIA_TYPE_AUDIO && AV_GET_CODEC_ATTRIBUTES(audio_st, audio_codec)->frame_size <= 1)
561  return;
562 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
563  if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO)
564  return;
565 #endif
566 
567  int error_code = 0;
568  int stop_encoding = 1;
569 
570  // FLUSH VIDEO ENCODER
571  if (info.has_video)
572  for (;;) {
573 
574  // Increment PTS (in frames and scaled to the codec's timebase)
575  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
576 
577  AVPacket pkt;
578  av_init_packet(&pkt);
579  pkt.data = NULL;
580  pkt.size = 0;
581 
582  // Pointer for video buffer (if using old FFmpeg version)
583  uint8_t *video_outbuf = NULL;
584 
585  /* encode the image */
586  int got_packet = 0;
587  int error_code = 0;
588 
589  #if IS_FFMPEG_3_2
590  #pragma omp critical (write_video_packet)
591  {
592  // Encode video packet (latest version of FFmpeg)
593  error_code = avcodec_send_frame(video_codec, NULL);
594  got_packet = 0;
595  while (error_code >= 0) {
596  error_code = avcodec_receive_packet(video_codec, &pkt);
597  if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
598  got_packet = 0;
599  // Write packet
600  avcodec_flush_buffers(video_codec);
601  break;
602  }
603  if (pkt.pts != AV_NOPTS_VALUE)
604  pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
605  if (pkt.dts != AV_NOPTS_VALUE)
606  pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
607  if (pkt.duration > 0)
608  pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
609  pkt.stream_index = video_st->index;
610  error_code = av_interleaved_write_frame(oc, &pkt);
611  }
612  }
613  #else
614 
615  #if LIBAVFORMAT_VERSION_MAJOR >= 54
616  // Encode video packet (older than FFmpeg 3.2)
617  error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
618 
619  #else
620  // Encode video packet (even older version of FFmpeg)
621  int video_outbuf_size = 0;
622 
623  /* encode the image */
624  int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
625 
626  /* if zero size, it means the image was buffered */
627  if (out_size > 0) {
628  if(video_codec->coded_frame->key_frame)
629  pkt.flags |= AV_PKT_FLAG_KEY;
630  pkt.data= video_outbuf;
631  pkt.size= out_size;
632 
633  // got data back (so encode this frame)
634  got_packet = 1;
635  }
636  #endif
637  #endif
638 
639  if (error_code < 0) {
640  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
641  }
642  if (!got_packet) {
643  stop_encoding = 1;
644  break;
645  }
646 
647  // Override PTS (in frames and scaled to the codec's timebase)
648  //pkt.pts = write_video_count;
649 
650  // set the timestamp
651  if (pkt.pts != AV_NOPTS_VALUE)
652  pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
653  if (pkt.dts != AV_NOPTS_VALUE)
654  pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
655  if (pkt.duration > 0)
656  pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
657  pkt.stream_index = video_st->index;
658 
659  // Write packet
660  error_code = av_interleaved_write_frame(oc, &pkt);
661  if (error_code < 0) {
662  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
663  }
664 
665  // Deallocate memory (if needed)
666  if (video_outbuf)
667  av_freep(&video_outbuf);
668  }
669 
670  // FLUSH AUDIO ENCODER
671  if (info.has_audio)
672  for (;;) {
673 
674  // Increment PTS (in samples and scaled to the codec's timebase)
675 #if LIBAVFORMAT_VERSION_MAJOR >= 54
676  // for some reason, it requires me to multiply channels X 2
677  write_audio_count += av_rescale_q(audio_input_position / (audio_codec->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)), (AVRational){1, info.sample_rate}, audio_codec->time_base);
678 #else
679  write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
680 #endif
681 
682  AVPacket pkt;
683  av_init_packet(&pkt);
684  pkt.data = NULL;
685  pkt.size = 0;
686  pkt.pts = pkt.dts = write_audio_count;
687 
688  /* encode the image */
689  int got_packet = 0;
690  #if IS_FFMPEG_3_2
691  avcodec_send_frame(audio_codec, NULL);
692  got_packet = 0;
693  #else
694  error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
695  #endif
696  if (error_code < 0) {
697  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
698  }
699  if (!got_packet) {
700  stop_encoding = 1;
701  break;
702  }
703 
704  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
705  // but it fixes lots of PTS related issues when I do this.
706  pkt.pts = pkt.dts = write_audio_count;
707 
708  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
709  if (pkt.pts != AV_NOPTS_VALUE)
710  pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
711  if (pkt.dts != AV_NOPTS_VALUE)
712  pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
713  if (pkt.duration > 0)
714  pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
715 
716  // set stream
717  pkt.stream_index = audio_st->index;
718  pkt.flags |= AV_PKT_FLAG_KEY;
719 
720  // Write packet
721  error_code = av_interleaved_write_frame(oc, &pkt);
722  if (error_code < 0) {
723  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
724  }
725 
726  // deallocate memory for packet
727  AV_FREE_PACKET(&pkt);
728  }
729 
730 
731 }
732 
733 // Close the video codec
734 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
735 {
736  AV_FREE_CONTEXT(video_codec);
737  video_codec = NULL;
738 }
739 
740 // Close the audio codec
741 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
742 {
743  AV_FREE_CONTEXT(audio_codec);
744  audio_codec = NULL;
745 
746  // Clear buffers
747  delete[] samples;
748  delete[] audio_outbuf;
749  delete[] audio_encoder_buffer;
750  samples = NULL;
751  audio_outbuf = NULL;
752  audio_encoder_buffer = NULL;
753 
754  // Deallocate resample buffer
755  if (avr) {
756  SWR_CLOSE(avr);
757  SWR_FREE(&avr);
758  avr = NULL;
759  }
760 
761  if (avr_planar) {
762  SWR_CLOSE(avr_planar);
763  SWR_FREE(&avr_planar);
764  avr_planar = NULL;
765  }
766 }
767 
768 // Close the writer
770 {
771  // Write trailer (if needed)
772  if (!write_trailer)
773  WriteTrailer();
774 
775  // Close each codec
776  if (video_st)
777  close_video(oc, video_st);
778  if (audio_st)
779  close_audio(oc, audio_st);
780 
781  // Deallocate image scalers
782  if (image_rescalers.size() > 0)
783  RemoveScalers();
784 
785  // Free the streams
786  for (int i = 0; i < oc->nb_streams; i++) {
787  av_freep(AV_GET_CODEC_ATTRIBUTES(&oc->streams[i], &oc->streams[i]));
788  av_freep(&oc->streams[i]);
789  }
790 
791  if (!(fmt->flags & AVFMT_NOFILE)) {
792  /* close the output file */
793  avio_close(oc->pb);
794  }
795 
796  // Reset frame counters
797  write_video_count = 0;
798  write_audio_count = 0;
799 
800  // Free the context
801  av_freep(&oc);
802 
803  // Close writer
804  is_open = false;
805  prepare_streams = false;
806  write_header = false;
807  write_trailer = false;
808 
809  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::Close", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
810 }
811 
812 // Add an AVFrame to the cache
813 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
814 {
815  // Add AVFrame to map (if it does not already exist)
816  if (!av_frames.count(frame))
817  {
818  // Add av_frame
819  av_frames[frame] = av_frame;
820  }
821  else
822  {
823  // Do not add, and deallocate this AVFrame
824  AV_FREE_FRAME(&av_frame);
825  }
826 }
827 
828 // Add an audio output stream
829 AVStream* FFmpegWriter::add_audio_stream()
830 {
831  AVCodecContext *c;
832  AVStream *st;
833 
834  // Find the audio codec
835  AVCodec *codec = avcodec_find_encoder_by_name(info.acodec.c_str());
836  if (codec == NULL)
837  throw InvalidCodec("A valid audio codec could not be found for this file.", path);
838 
839  // Create a new audio stream
840  AV_FORMAT_NEW_STREAM(oc, audio_codec, codec, st)
841 
842  c->codec_id = codec->id;
843 #if LIBAVFORMAT_VERSION_MAJOR >= 53
844  c->codec_type = AVMEDIA_TYPE_AUDIO;
845 #else
846  c->codec_type = CODEC_TYPE_AUDIO;
847 #endif
848 
849  // Set the sample parameters
850  c->bit_rate = info.audio_bit_rate;
851  c->channels = info.channels;
852 
853  // Set valid sample rate (or throw error)
854  if (codec->supported_samplerates) {
855  int i;
856  for (i = 0; codec->supported_samplerates[i] != 0; i++)
857  if (info.sample_rate == codec->supported_samplerates[i])
858  {
859  // Set the valid sample rate
860  c->sample_rate = info.sample_rate;
861  break;
862  }
863  if (codec->supported_samplerates[i] == 0)
864  throw InvalidSampleRate("An invalid sample rate was detected for this codec.", path);
865  } else
866  // Set sample rate
867  c->sample_rate = info.sample_rate;
868 
869 
870  // Set a valid number of channels (or throw error)
871  int channel_layout = info.channel_layout;
872  if (codec->channel_layouts) {
873  int i;
874  for (i = 0; codec->channel_layouts[i] != 0; i++)
875  if (channel_layout == codec->channel_layouts[i])
876  {
877  // Set valid channel layout
878  c->channel_layout = channel_layout;
879  break;
880  }
881  if (codec->channel_layouts[i] == 0)
882  throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
883  } else
884  // Set valid channel layout
885  c->channel_layout = channel_layout;
886 
887  // Choose a valid sample_fmt
888  if (codec->sample_fmts) {
889  for (int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
890  {
891  // Set sample format to 1st valid format (and then exit loop)
892  c->sample_fmt = codec->sample_fmts[i];
893  break;
894  }
895  }
896  if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
897  // Default if no sample formats found
898  c->sample_fmt = AV_SAMPLE_FMT_S16;
899  }
900 
901  // some formats want stream headers to be separate
902  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
903 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
904  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
905 #else
906  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
907 #endif
908 
910  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_audio_stream", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->channels", c->channels, "c->sample_fmt", c->sample_fmt, "c->channel_layout", c->channel_layout, "c->sample_rate", c->sample_rate);
911 
912  return st;
913 }
914 
915 // Add a video output stream
916 AVStream* FFmpegWriter::add_video_stream()
917 {
918  AVCodecContext *c;
919  AVStream *st;
920 
921  // Find the video codec
922  AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
923  if (codec == NULL)
924  throw InvalidCodec("A valid video codec could not be found for this file.", path);
925 
926  // Create a new video stream
927  AV_FORMAT_NEW_STREAM(oc, video_codec, codec, st)
928 
929  c->codec_id = codec->id;
930 #if LIBAVFORMAT_VERSION_MAJOR >= 53
931  c->codec_type = AVMEDIA_TYPE_VIDEO;
932 #else
933  c->codec_type = CODEC_TYPE_VIDEO;
934 #endif
935 
936  /* Init video encoder options */
937  c->bit_rate = info.video_bit_rate;
938 
939  //TODO: Implement variable bitrate feature (which actually works). This implementation throws
940  //invalid bitrate errors and rc buffer underflow errors, etc...
941  //c->rc_min_rate = info.video_bit_rate;
942  //c->rc_max_rate = info.video_bit_rate;
943  //c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
944  //if ( !c->rc_initial_buffer_occupancy )
945  // c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
946  c->qmin = 2;
947  c->qmax = 30;
948 
949  /* resolution must be a multiple of two */
950  // TODO: require /2 height and width
951  c->width = info.width;
952  c->height = info.height;
953 
954  /* time base: this is the fundamental unit of time (in seconds) in terms
955  of which frame timestamps are represented. for fixed-fps content,
956  timebase should be 1/framerate and timestamp increments should be
957  identically 1. */
958  c->time_base.num = info.video_timebase.num;
959  c->time_base.den = info.video_timebase.den;
960  #if LIBAVFORMAT_VERSION_MAJOR >= 56
961  c->framerate = av_inv_q(c->time_base);
962  #endif
963  st->avg_frame_rate = av_inv_q(c->time_base);
964  st->time_base.num = info.video_timebase.num;
965  st->time_base.den = info.video_timebase.den;
966 
967  c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
968  c->max_b_frames = 10;
969  if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
970  /* just for testing, we also add B frames */
971  c->max_b_frames = 2;
972  if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
973  /* Needed to avoid using macroblocks in which some coeffs overflow.
974  This does not happen with normal video, it just happens here as
975  the motion of the chroma plane does not match the luma plane. */
976  c->mb_decision = 2;
977  // some formats want stream headers to be separate
978  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
979 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
980  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
981 #else
982  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
983 #endif
984 
985  // Find all supported pixel formats for this codec
986  const PixelFormat* supported_pixel_formats = codec->pix_fmts;
987  while (supported_pixel_formats != NULL && *supported_pixel_formats != PIX_FMT_NONE) {
988  // Assign the 1st valid pixel format (if one is missing)
989  if (c->pix_fmt == PIX_FMT_NONE)
990  c->pix_fmt = *supported_pixel_formats;
991  ++supported_pixel_formats;
992  }
993 
994  // Codec doesn't have any pix formats?
995  if (c->pix_fmt == PIX_FMT_NONE) {
996  if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
997  // Raw video should use RGB24
998  c->pix_fmt = PIX_FMT_RGB24;
999 
1000 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1001  if (strcmp(fmt->name, "gif") != 0)
1002  // If not GIF format, skip the encoding process
1003  // Set raw picture flag (so we don't encode this video)
1004  oc->oformat->flags |= AVFMT_RAWPICTURE;
1005 #endif
1006  } else {
1007  // Set the default codec
1008  c->pix_fmt = PIX_FMT_YUV420P;
1009  }
1010  }
1011 
1013 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1014  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (string)fmt->name + " : " + (string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "AVFMT_RAWPICTURE", AVFMT_RAWPICTURE, "", -1);
1015 #else
1016  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (string)fmt->name + " : " + (string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "", -1, "", -1);
1017 #endif
1018 
1019  return st;
1020 }
1021 
1022 // open audio codec
1023 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
1024 {
1025  AVCodec *codec;
1026  AV_GET_CODEC_FROM_STREAM(st, audio_codec)
1027 
1028  // Set number of threads equal to number of processors (not to exceed 16)
1029  audio_codec->thread_count = min(FF_NUM_PROCESSORS, 16);
1030 
1031  // Find the audio encoder
1032  codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1033  if (!codec)
1034  codec = avcodec_find_encoder(audio_codec->codec_id);
1035  if (!codec)
1036  throw InvalidCodec("Could not find codec", path);
1037 
1038  // Init options
1039  AVDictionary *opts = NULL;
1040  av_dict_set(&opts, "strict", "experimental", 0);
1041 
1042  // Open the codec
1043  if (avcodec_open2(audio_codec, codec, &opts) < 0)
1044  throw InvalidCodec("Could not open codec", path);
1045  AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec);
1046 
1047  // Free options
1048  av_dict_free(&opts);
1049 
1050  // Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
1051  // TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
1052  if (audio_codec->frame_size <= 1) {
1053  // No frame size found... so calculate
1054  audio_input_frame_size = 50000 / info.channels;
1055 
1056  int s = AV_FIND_DECODER_CODEC_ID(st);
1057  switch (s) {
1058  case AV_CODEC_ID_PCM_S16LE:
1059  case AV_CODEC_ID_PCM_S16BE:
1060  case AV_CODEC_ID_PCM_U16LE:
1061  case AV_CODEC_ID_PCM_U16BE:
1062  audio_input_frame_size >>= 1;
1063  break;
1064  default:
1065  break;
1066  }
1067  } else {
1068  // Set frame size based on the codec
1069  audio_input_frame_size = audio_codec->frame_size;
1070  }
1071 
1072  // Set the initial frame size (since it might change during resampling)
1073  initial_audio_input_frame_size = audio_input_frame_size;
1074 
1075  // Allocate array for samples
1076  samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
1077 
1078  // Set audio output buffer (used to store the encoded audio)
1079  audio_outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
1080  audio_outbuf = new uint8_t[audio_outbuf_size];
1081 
1082  // Set audio packet encoding buffer
1083  audio_encoder_buffer_size = AUDIO_PACKET_ENCODING_SIZE;
1084  audio_encoder_buffer = new uint8_t[audio_encoder_buffer_size];
1085 
1086  // Add audio metadata (if any)
1087  for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
1088  {
1089  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1090  }
1091 
1092  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_audio", "audio_codec->thread_count", audio_codec->thread_count, "audio_input_frame_size", audio_input_frame_size, "buffer_size", AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE, "", -1, "", -1, "", -1);
1093 
1094 }
1095 
1096 // open video codec
1097 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1098 {
1099  AVCodec *codec;
1100  AV_GET_CODEC_FROM_STREAM(st, video_codec)
1101 
1102  // Set number of threads equal to number of processors (not to exceed 16)
1103  video_codec->thread_count = min(FF_NUM_PROCESSORS, 16);
1104 
1105  /* find the video encoder */
1106  codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1107  if (!codec)
1108  codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
1109  if (!codec)
1110  throw InvalidCodec("Could not find codec", path);
1111 
1112  /* Force max_b_frames to 0 in some cases (i.e. for mjpeg image sequences */
1113  if(video_codec->max_b_frames && video_codec->codec_id != AV_CODEC_ID_MPEG4 && video_codec->codec_id != AV_CODEC_ID_MPEG1VIDEO && video_codec->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1114  video_codec->max_b_frames = 0;
1115 
1116  // Init options
1117  AVDictionary *opts = NULL;
1118  av_dict_set(&opts, "strict", "experimental", 0);
1119 
1120  /* open the codec */
1121  if (avcodec_open2(video_codec, codec, &opts) < 0)
1122  throw InvalidCodec("Could not open codec", path);
1123  AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec);
1124 
1125  // Free options
1126  av_dict_free(&opts);
1127 
1128  // Add video metadata (if any)
1129  for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
1130  {
1131  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1132  }
1133 
1134  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video", "video_codec->thread_count", video_codec->thread_count, "", -1, "", -1, "", -1, "", -1, "", -1);
1135 
1136 }
1137 
1138 // write all queued frames' audio to the video file
1139 void FFmpegWriter::write_audio_packets(bool final)
1140 {
1141  #pragma omp task firstprivate(final)
1142  {
1143  // Init audio buffers / variables
1144  int total_frame_samples = 0;
1145  int frame_position = 0;
1146  int channels_in_frame = 0;
1147  int sample_rate_in_frame = 0;
1148  int samples_in_frame = 0;
1149  ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
1150 
1151  // Create a new array (to hold all S16 audio samples, for the current queued frames
1152  int16_t* all_queued_samples = (int16_t*)av_malloc((sizeof(int16_t)*(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE)));
1153  int16_t* all_resampled_samples = NULL;
1154  int16_t* final_samples_planar = NULL;
1155  int16_t* final_samples = NULL;
1156 
1157  // Loop through each queued audio frame
1158  while (!queued_audio_frames.empty())
1159  {
1160  // Get front frame (from the queue)
1161  std::shared_ptr<Frame> frame = queued_audio_frames.front();
1162 
1163  // Get the audio details from this frame
1164  sample_rate_in_frame = frame->SampleRate();
1165  samples_in_frame = frame->GetAudioSamplesCount();
1166  channels_in_frame = frame->GetAudioChannelsCount();
1167  channel_layout_in_frame = frame->ChannelsLayout();
1168 
1169 
1170  // Get audio sample array
1171  float* frame_samples_float = NULL;
1172  // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
1173  frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1174 
1175 
1176  // Calculate total samples
1177  total_frame_samples = samples_in_frame * channels_in_frame;
1178 
1179  // Translate audio sample values back to 16 bit integers
1180  for (int s = 0; s < total_frame_samples; s++, frame_position++)
1181  // Translate sample value and copy into buffer
1182  all_queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
1183 
1184 
1185  // Deallocate float array
1186  delete[] frame_samples_float;
1187 
1188  // Remove front item
1189  queued_audio_frames.pop_front();
1190 
1191  } // end while
1192 
1193 
1194  // Update total samples (since we've combined all queued frames)
1195  total_frame_samples = frame_position;
1196  int remaining_frame_samples = total_frame_samples;
1197  int samples_position = 0;
1198 
1199 
1200  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets", "final", final, "total_frame_samples", total_frame_samples, "channel_layout_in_frame", channel_layout_in_frame, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "LAYOUT_MONO", LAYOUT_MONO);
1201 
1202  // Keep track of the original sample format
1203  AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1204 
1205  AVFrame *audio_frame = NULL;
1206  if (!final) {
1207  // Create input frame (and allocate arrays)
1208  audio_frame = AV_ALLOCATE_FRAME();
1209  AV_RESET_FRAME(audio_frame);
1210  audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1211 
1212  // Fill input frame with sample data
1213  avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1214  audio_encoder_buffer_size, 0);
1215 
1216  // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
1217  switch (audio_codec->sample_fmt)
1218  {
1219  case AV_SAMPLE_FMT_FLTP:
1220  {
1221  output_sample_fmt = AV_SAMPLE_FMT_FLT;
1222  break;
1223  }
1224  case AV_SAMPLE_FMT_S32P:
1225  {
1226  output_sample_fmt = AV_SAMPLE_FMT_S32;
1227  break;
1228  }
1229  case AV_SAMPLE_FMT_S16P:
1230  {
1231  output_sample_fmt = AV_SAMPLE_FMT_S16;
1232  break;
1233  }
1234  case AV_SAMPLE_FMT_U8P:
1235  {
1236  output_sample_fmt = AV_SAMPLE_FMT_U8;
1237  break;
1238  }
1239  }
1240 
1241  // Update total samples & input frame size (due to bigger or smaller data types)
1242  total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
1243  total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
1244 
1245  // Set remaining samples
1246  remaining_frame_samples = total_frame_samples;
1247 
1248  // Create output frame (and allocate arrays)
1249  AVFrame *audio_converted = AV_ALLOCATE_FRAME();
1250  AV_RESET_FRAME(audio_converted);
1251  audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1252  av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
1253 
1254  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (1st resampling)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", output_sample_fmt, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
1255 
1256  // setup resample context
1257  if (!avr) {
1258  avr = SWR_ALLOC();
1259  av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
1260  av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
1261  av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1262  av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
1263  av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
1264  av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1265  av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1266  av_opt_set_int(avr, "out_channels", info.channels, 0);
1267  SWR_INIT(avr);
1268  }
1269  int nb_samples = 0;
1270 
1271  // Convert audio samples
1272  nb_samples = SWR_CONVERT(avr, // audio resample context
1273  audio_converted->data, // output data pointers
1274  audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
1275  audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
1276  audio_frame->data, // input data pointers
1277  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1278  audio_frame->nb_samples); // number of input samples to convert
1279 
1280  // Create a new array (to hold all resampled S16 audio samples)
1281  all_resampled_samples = (int16_t*)av_malloc(sizeof(int16_t) * nb_samples * info.channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1282 
1283  // Copy audio samples over original samples
1284  memcpy(all_resampled_samples, audio_converted->data[0], nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1285 
1286  // Remove converted audio
1287  av_freep(&(audio_frame->data[0]));
1288  AV_FREE_FRAME(&audio_frame);
1289  av_freep(&audio_converted->data[0]);
1290  AV_FREE_FRAME(&audio_converted);
1291  all_queued_samples = NULL; // this array cleared with above call
1292 
1293  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)", "nb_samples", nb_samples, "remaining_frame_samples", remaining_frame_samples, "", -1, "", -1, "", -1, "", -1);
1294  }
1295 
1296  // Loop until no more samples
1297  while (remaining_frame_samples > 0 || final) {
1298  // Get remaining samples needed for this packet
1299  int remaining_packet_samples = (audio_input_frame_size * info.channels) - audio_input_position;
1300 
1301  // Determine how many samples we need
1302  int diff = 0;
1303  if (remaining_frame_samples >= remaining_packet_samples)
1304  diff = remaining_packet_samples;
1305  else if (remaining_frame_samples < remaining_packet_samples)
1306  diff = remaining_frame_samples;
1307 
1308  // Copy frame samples into the packet samples array
1309  if (!final)
1310  //TODO: Make this more sane
1311  memcpy(samples + (audio_input_position * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))), all_resampled_samples + samples_position, diff * av_get_bytes_per_sample(output_sample_fmt));
1312 
1313  // Increment counters
1314  audio_input_position += diff;
1315  samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1316  remaining_frame_samples -= diff;
1317  remaining_packet_samples -= diff;
1318 
1319  // Do we have enough samples to proceed?
1320  if (audio_input_position < (audio_input_frame_size * info.channels) && !final)
1321  // Not enough samples to encode... so wait until the next frame
1322  break;
1323 
1324  // Convert to planar (if needed by audio codec)
1325  AVFrame *frame_final = AV_ALLOCATE_FRAME();
1326  AV_RESET_FRAME(frame_final);
1327  if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1328  {
1329  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)", "in_sample_fmt", output_sample_fmt, "out_sample_fmt", audio_codec->sample_fmt, "in_sample_rate", info.sample_rate, "out_sample_rate", info.sample_rate, "in_channels", info.channels, "out_channels", info.channels);
1330 
1331  // setup resample context
1332  if (!avr_planar) {
1333  avr_planar = SWR_ALLOC();
1334  av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
1335  av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
1336  av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
1337  av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec->sample_fmt, 0); // planar not allowed here
1338  av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
1339  av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
1340  av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1341  av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
1342  SWR_INIT(avr_planar);
1343  }
1344 
1345  // Create input frame (and allocate arrays)
1346  audio_frame = AV_ALLOCATE_FRAME();
1347  AV_RESET_FRAME(audio_frame);
1348  audio_frame->nb_samples = audio_input_position / info.channels;
1349 
1350  // Create a new array
1351  final_samples_planar = (int16_t*)av_malloc(sizeof(int16_t) * audio_frame->nb_samples * info.channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1352 
1353  // Copy audio into buffer for frame
1354  memcpy(final_samples_planar, samples, audio_frame->nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1355 
1356  // Fill input frame with sample data
1357  avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1358  audio_encoder_buffer_size, 0);
1359 
1360  // Create output frame (and allocate arrays)
1361  frame_final->nb_samples = audio_input_frame_size;
1362  av_samples_alloc(frame_final->data, frame_final->linesize, info.channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1363 
1364  // Convert audio samples
1365  int nb_samples = SWR_CONVERT(avr_planar, // audio resample context
1366  frame_final->data, // output data pointers
1367  frame_final->linesize[0], // output plane size, in bytes. (0 if unknown)
1368  frame_final->nb_samples, // maximum number of samples that the output buffer can hold
1369  audio_frame->data, // input data pointers
1370  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1371  audio_frame->nb_samples); // number of input samples to convert
1372 
1373  // Copy audio samples over original samples
1374  if (nb_samples > 0)
1375  memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels);
1376 
1377  // deallocate AVFrame
1378  av_freep(&(audio_frame->data[0]));
1379  AV_FREE_FRAME(&audio_frame);
1380  all_queued_samples = NULL; // this array cleared with above call
1381 
1382  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)", "nb_samples", nb_samples, "", -1, "", -1, "", -1, "", -1, "", -1);
1383 
1384  } else {
1385  // Create a new array
1386  final_samples = new int16_t[audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))];
1387 
1388  // Copy audio into buffer for frame
1389  memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1390 
1391  // Init the nb_samples property
1392  frame_final->nb_samples = audio_input_frame_size;
1393 
1394  // Fill the final_frame AVFrame with audio (non planar)
1395  avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1396  audio_encoder_buffer_size, 0);
1397  }
1398 
1399  // Increment PTS (in samples)
1400  write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1401  frame_final->pts = write_audio_count; // Set the AVFrame's PTS
1402 
1403  // Init the packet
1404  AVPacket pkt;
1405  av_init_packet(&pkt);
1406  pkt.data = audio_encoder_buffer;
1407  pkt.size = audio_encoder_buffer_size;
1408 
1409  // Set the packet's PTS prior to encoding
1410  pkt.pts = pkt.dts = write_audio_count;
1411 
1412  /* encode the audio samples */
1413  int got_packet_ptr = 0;
1414 
1415  #if IS_FFMPEG_3_2
1416  // Encode audio (latest version of FFmpeg)
1417  int error_code;
1418  int ret = 0;
1419  int frame_finished = 0;
1420  error_code = ret = avcodec_send_frame(audio_codec, frame_final);
1421  if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1422  avcodec_send_frame(audio_codec, NULL);
1423  }
1424  else {
1425  if (ret >= 0)
1426  pkt.size = 0;
1427  ret = avcodec_receive_packet(audio_codec, &pkt);
1428  if (ret >= 0)
1429  frame_finished = 1;
1430  if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1431  avcodec_flush_buffers(audio_codec);
1432  ret = 0;
1433  }
1434  if (ret >= 0) {
1435  ret = frame_finished;
1436  }
1437  }
1438  if (!pkt.data && !frame_finished)
1439  {
1440  ret = -1;
1441  }
1442  got_packet_ptr = ret;
1443  #else
1444  // Encode audio (older versions of FFmpeg)
1445  int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1446  #endif
1447  /* if zero size, it means the image was buffered */
1448  if (error_code == 0 && got_packet_ptr) {
1449 
1450  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1451  // but it fixes lots of PTS related issues when I do this.
1452  pkt.pts = pkt.dts = write_audio_count;
1453 
1454  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
1455  if (pkt.pts != AV_NOPTS_VALUE)
1456  pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1457  if (pkt.dts != AV_NOPTS_VALUE)
1458  pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1459  if (pkt.duration > 0)
1460  pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1461 
1462  // set stream
1463  pkt.stream_index = audio_st->index;
1464  pkt.flags |= AV_PKT_FLAG_KEY;
1465 
1466  /* write the compressed frame in the media file */
1467  int error_code = av_interleaved_write_frame(oc, &pkt);
1468  if (error_code < 0)
1469  {
1470  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1471  }
1472  }
1473 
1474  if (error_code < 0)
1475  {
1476  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1477  }
1478 
1479  // deallocate AVFrame
1480  av_freep(&(frame_final->data[0]));
1481  AV_FREE_FRAME(&frame_final);
1482 
1483  // deallocate memory for packet
1484  AV_FREE_PACKET(&pkt);
1485 
1486  // Reset position
1487  audio_input_position = 0;
1488  final = false;
1489  }
1490 
1491  // Delete arrays (if needed)
1492  if (all_resampled_samples) {
1493  av_freep(&all_resampled_samples);
1494  all_resampled_samples = NULL;
1495  }
1496  if (all_queued_samples) {
1497  av_freep(&all_queued_samples);
1498  all_queued_samples = NULL;
1499  }
1500 
1501  } // end task
1502 }
1503 
1504 // Allocate an AVFrame object
1505 AVFrame* FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer)
1506 {
1507  // Create an RGB AVFrame
1508  AVFrame *new_av_frame = NULL;
1509 
1510  // Allocate an AVFrame structure
1511  new_av_frame = AV_ALLOCATE_FRAME();
1512  if (new_av_frame == NULL)
1513  throw OutOfMemory("Could not allocate AVFrame", path);
1514 
1515  // Determine required buffer size and allocate buffer
1516  *buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
1517 
1518  // Create buffer (if not provided)
1519  if (!new_buffer)
1520  {
1521  // New Buffer
1522  new_buffer = (uint8_t*)av_malloc(*buffer_size * sizeof(uint8_t));
1523  // Attach buffer to AVFrame
1524  AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
1525  new_av_frame->width = width;
1526  new_av_frame->height = height;
1527  new_av_frame->format = pix_fmt;
1528  }
1529 
1530  // return AVFrame
1531  return new_av_frame;
1532 }
1533 
1534 // process video frame
1535 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1536 {
1537  // Determine the height & width of the source image
1538  int source_image_width = frame->GetWidth();
1539  int source_image_height = frame->GetHeight();
1540 
1541  // Do nothing if size is 1x1 (i.e. no image in this frame)
1542  if (source_image_height == 1 && source_image_width == 1)
1543  return;
1544 
1545  // Init rescalers (if not initialized yet)
1546  if (image_rescalers.size() == 0)
1547  InitScalers(source_image_width, source_image_height);
1548 
1549  // Get a unique rescaler (for this thread)
1550  SwsContext *scaler = image_rescalers[rescaler_position];
1551  rescaler_position++;
1552  if (rescaler_position == num_of_rescalers)
1553  rescaler_position = 0;
1554 
1555  #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height)
1556  {
1557  // Allocate an RGB frame & final output frame
1558  int bytes_source = 0;
1559  int bytes_final = 0;
1560  AVFrame *frame_source = NULL;
1561  const uchar *pixels = NULL;
1562 
1563  // Get a list of pixels from source image
1564  pixels = frame->GetPixels();
1565 
1566  // Init AVFrame for source image & final (converted image)
1567  frame_source = allocate_avframe(PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1568  #if IS_FFMPEG_3_2
1569  AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format), info.width, info.height, &bytes_final, NULL);
1570  #else
1571  AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt, info.width, info.height, &bytes_final, NULL);
1572  #endif
1573 
1574  // Fill with data
1575  AV_COPY_PICTURE_DATA(frame_source, (uint8_t*)pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
1576  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::process_video_packet", "frame->number", frame->number, "bytes_source", bytes_source, "bytes_final", bytes_final, "", -1, "", -1, "", -1);
1577 
1578  // Resize & convert pixel format
1579  sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1580  source_image_height, frame_final->data, frame_final->linesize);
1581 
1582  // Add resized AVFrame to av_frames map
1583  #pragma omp critical (av_frames_section)
1584  add_avframe(frame, frame_final);
1585 
1586  // Deallocate memory
1587  AV_FREE_FRAME(&frame_source);
1588 
1589  } // end task
1590 
1591 }
1592 
1593 // write video frame
1594 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1595 {
1596 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1597  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags, "", -1, "", -1, "", -1, "", -1);
1598 #else
1599  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE, "", -1, "", -1, "", -1, "", -1);
1600 
1601  if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1602  // Raw video case.
1603  AVPacket pkt;
1604  av_init_packet(&pkt);
1605 
1606  pkt.flags |= AV_PKT_FLAG_KEY;
1607  pkt.stream_index= video_st->index;
1608  pkt.data= (uint8_t*)frame_final->data;
1609  pkt.size= sizeof(AVPicture);
1610 
1611  // Increment PTS (in frames and scaled to the codec's timebase)
1612  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
1613  pkt.pts = write_video_count;
1614 
1615  /* write the compressed frame in the media file */
1616  int error_code = av_interleaved_write_frame(oc, &pkt);
1617  if (error_code < 0)
1618  {
1619  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1620  return false;
1621  }
1622 
1623  // Deallocate packet
1624  AV_FREE_PACKET(&pkt);
1625 
1626  } else
1627 #endif
1628  {
1629 
1630  AVPacket pkt;
1631  av_init_packet(&pkt);
1632  pkt.data = NULL;
1633  pkt.size = 0;
1634  pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1635 
1636  // Pointer for video buffer (if using old FFmpeg version)
1637  uint8_t *video_outbuf = NULL;
1638 
1639  // Increment PTS (in frames and scaled to the codec's timebase)
1640  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
1641 
1642  // Assign the initial AVFrame PTS from the frame counter
1643  frame_final->pts = write_video_count;
1644 
1645  /* encode the image */
1646  int got_packet_ptr = 0;
1647  int error_code = 0;
1648  #if IS_FFMPEG_3_2
1649  // Write video packet (latest version of FFmpeg)
1650  int frameFinished = 0;
1651  int ret = avcodec_send_frame(video_codec, frame_final);
1652  error_code = ret;
1653  if (ret < 0 ) {
1654  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent)", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
1655  if (ret == AVERROR(EAGAIN) )
1656  cerr << "Frame EAGAIN" << "\n";
1657  if (ret == AVERROR_EOF )
1658  cerr << "Frame AVERROR_EOF" << "\n";
1659  avcodec_send_frame(video_codec, NULL);
1660  }
1661  else {
1662  while (ret >= 0) {
1663  ret = avcodec_receive_packet(video_codec, &pkt);
1664  if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1665  avcodec_flush_buffers(video_codec);
1666  got_packet_ptr = 0;
1667  break;
1668  }
1669  if (ret == 0) {
1670  got_packet_ptr = 1;
1671  break;
1672  }
1673  }
1674  }
1675  #else
1676  #if LIBAVFORMAT_VERSION_MAJOR >= 54
1677  // Write video packet (older than FFmpeg 3.2)
1678  error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1679  if (error_code != 0 )
1680  cerr << "Frame AVERROR_EOF" << "\n";
1681  if (got_packet_ptr == 0 )
1682  cerr << "Frame gotpacket error" << "\n";
1683  #else
1684  // Write video packet (even older versions of FFmpeg)
1685  int video_outbuf_size = 200000;
1686  video_outbuf = (uint8_t*) av_malloc(200000);
1687 
1688  /* encode the image */
1689  int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1690 
1691  /* if zero size, it means the image was buffered */
1692  if (out_size > 0) {
1693  if(video_codec->coded_frame->key_frame)
1694  pkt.flags |= AV_PKT_FLAG_KEY;
1695  pkt.data= video_outbuf;
1696  pkt.size= out_size;
1697 
1698  // got data back (so encode this frame)
1699  got_packet_ptr = 1;
1700  }
1701  #endif
1702  #endif
1703 
1704  /* if zero size, it means the image was buffered */
1705  if (error_code == 0 && got_packet_ptr) {
1706 
1707  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1708  // but it fixes lots of PTS related issues when I do this.
1709  //pkt.pts = pkt.dts = write_video_count;
1710 
1711  // set the timestamp
1712  if (pkt.pts != AV_NOPTS_VALUE)
1713  pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1714  if (pkt.dts != AV_NOPTS_VALUE)
1715  pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1716  if (pkt.duration > 0)
1717  pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1718  pkt.stream_index = video_st->index;
1719 
1720  /* write the compressed frame in the media file */
1721  int error_code = av_interleaved_write_frame(oc, &pkt);
1722  if (error_code < 0)
1723  {
1724  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1725  return false;
1726  }
1727  }
1728 
1729  // Deallocate memory (if needed)
1730  if (video_outbuf)
1731  delete[] video_outbuf;
1732 
1733  // Deallocate packet
1734  AV_FREE_PACKET(&pkt);
1735  }
1736 
1737  // Success
1738  return true;
1739 }
1740 
1741 // Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
1743 {
1744  // output debug info
1745  av_dump_format(oc, 0, path.c_str(), 1);
1746 }
1747 
1748 // Init a collection of software rescalers (thread safe)
1749 void FFmpegWriter::InitScalers(int source_width, int source_height)
1750 {
1751  // Init software rescalers vector (many of them, one for each thread)
1752  for (int x = 0; x < num_of_rescalers; x++)
1753  {
1754  // Init the software scaler from FFMpeg
1755  img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), SWS_LANCZOS, NULL, NULL, NULL);
1756 
1757  // Add rescaler to vector
1758  image_rescalers.push_back(img_convert_ctx);
1759  }
1760 }
1761 
1762 // Set audio resample options
1763 void FFmpegWriter::ResampleAudio(int sample_rate, int channels) {
1764  original_sample_rate = sample_rate;
1765  original_channels = channels;
1766 }
1767 
1768 // Remove & deallocate all software scalers
1770 {
1771  // Close all rescalers
1772  for (int x = 0; x < num_of_rescalers; x++)
1773  sws_freeContext(image_rescalers[x]);
1774 
1775  // Clear vector
1776  image_rescalers.clear();
1777 }
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
Definition: WriterBase.h:72
A video stream (used to determine which type of stream)
Definition: FFmpegWriter.h:64
#define AV_FREE_FRAME(av_frame)
void SetOption(StreamType stream, string name, string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
int num
Numerator for the fraction.
Definition: Fraction.h:44
WriterInfo info
Information about the current media file.
Definition: WriterBase.h:93
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
An audio stream (used to determine which type of stream)
Definition: FFmpegWriter.h:65
#define SWR_INIT(ctx)
int video_bit_rate
The bit rate of the video stream (in bytes)
Definition: WriterBase.h:60
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Definition: WriterBase.h:61
Exception when an invalid # of audio channels are detected.
Definition: Exceptions.h:112
#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height)
#define AV_REGISTER_ALL
std::map< string, string > metadata
An optional map/dictionary of video & audio metadata.
Definition: WriterBase.h:76
#define PIX_FMT_RGB24
string acodec
The name of the audio codec used to encode / decode the video stream.
Definition: WriterBase.h:69
#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
string vcodec
The name of the video codec used to encode / decode the video stream.
Definition: WriterBase.h:63
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
Definition: Fraction.cpp:71
#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in)
#define AV_OPTION_FIND(priv_data, name)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
#define SWR_CLOSE(ctx)
#define SWR_FREE(ctx)
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:96
int width
The width of the video (in pixels)
Definition: WriterBase.h:57
int audio_bit_rate
The bit rate of the audio stream (in bytes)
Definition: WriterBase.h:70
#define OPEN_MP_NUM_PROCESSORS
void WriteFrame(std::shared_ptr< Frame > frame)
Add a frame to the stack waiting to be encoded.
Exception when encoding audio packet.
Definition: Exceptions.h:101
Exception when invalid sample rate is detected during encoding.
Definition: Exceptions.h:172
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition: WriterBase.h:66
void Open()
Open writer.
void SetVideoOptions(bool has_video, string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
virtual std::shared_ptr< Frame > GetFrame(int64_t number)=0
#define AV_FREE_CONTEXT(av_context)
Exception when no valid codec is found for a file.
Definition: Exceptions.h:122
Exception when memory could not be allocated.
Definition: Exceptions.h:224
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
Exception when invalid encoding options are used.
Definition: Exceptions.h:162
#define FF_NUM_PROCESSORS
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
Definition: Exceptions.h:192
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Definition: WriterBase.h:68
Exception for files that can not be found or opened.
Definition: Exceptions.h:132
FFmpegWriter(string path)
Constructor for FFmpegWriter. Throws one of the following exceptions.
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information.
Definition: ZmqLogger.cpp:162
This class represents a fraction.
Definition: Fraction.h:42
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
#define PIX_FMT_YUV420P
static bool IsValidCodec(string codec_name)
Determine if codec name is valid.
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
Definition: WriterBase.h:62
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
#define PixelFormat
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
#define av_err2str(errnum)
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
void Close()
Close the writer.
bool interlaced_frame
Are the contents of this frame interlaced.
Definition: WriterBase.h:67
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: WriterBase.h:71
#define MY_INPUT_BUFFER_PADDING_SIZE
#define AV_GET_IMAGE_SIZE(pix_fmt, width, height)
#define AV_OUTPUT_CONTEXT(output_context, path)
bool has_video
Determines if this file has a video stream.
Definition: WriterBase.h:51
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: WriterBase.h:59
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
Definition: ZmqLogger.cpp:38
#define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count)
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
#define SWR_ALLOC()
bool has_audio
Determines if this file has an audio stream.
Definition: WriterBase.h:52
#define PIX_FMT_RGBA
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate)
Set audio export options.
Exception when a writer is closed, and a frame is requested.
Definition: Exceptions.h:264
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition: WriterBase.h:73
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
int height
The height of the video (in pixels)
Definition: WriterBase.h:56
#define PIX_FMT_NONE
int den
Denominator for the fraction.
Definition: Fraction.h:45
#define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st)
Exception when no valid format is found for a file.
Definition: Exceptions.h:142
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)
Definition: FFmpegWriter.h:62
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)
#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)