OpenShot Library | libopenshot  0.2.0
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
49  av_register_all();
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
302  av_register_all();
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->filename, sizeof(oc->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 (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)
563  return;
564 
565  int error_code = 0;
566  int stop_encoding = 1;
567 
568  // FLUSH VIDEO ENCODER
569  if (info.has_video)
570  for (;;) {
571 
572  // Increment PTS (in frames and scaled to the codec's timebase)
573  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
574 
575  AVPacket pkt;
576  av_init_packet(&pkt);
577  pkt.data = NULL;
578  pkt.size = 0;
579 
580  // Pointer for video buffer (if using old FFmpeg version)
581  uint8_t *video_outbuf = NULL;
582 
583  /* encode the image */
584  int got_packet = 0;
585  int error_code = 0;
586 
587  #if IS_FFMPEG_3_2
588  #pragma omp critical (write_video_packet)
589  {
590  // Encode video packet (latest version of FFmpeg)
591  error_code = avcodec_send_frame(video_codec, NULL);
592  got_packet = 0;
593  }
594  #else
595 
596  #if LIBAVFORMAT_VERSION_MAJOR >= 54
597  // Encode video packet (older than FFmpeg 3.2)
598  error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
599 
600  #else
601  // Encode video packet (even older version of FFmpeg)
602  int video_outbuf_size = 0;
603 
604  /* encode the image */
605  int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
606 
607  /* if zero size, it means the image was buffered */
608  if (out_size > 0) {
609  if(video_codec->coded_frame->key_frame)
610  pkt.flags |= AV_PKT_FLAG_KEY;
611  pkt.data= video_outbuf;
612  pkt.size= out_size;
613 
614  // got data back (so encode this frame)
615  got_packet = 1;
616  }
617  #endif
618  #endif
619 
620  if (error_code < 0) {
621  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
622  }
623  if (!got_packet) {
624  stop_encoding = 1;
625  break;
626  }
627 
628  // Override PTS (in frames and scaled to the codec's timebase)
629  //pkt.pts = write_video_count;
630 
631  // set the timestamp
632  if (pkt.pts != AV_NOPTS_VALUE)
633  pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
634  if (pkt.dts != AV_NOPTS_VALUE)
635  pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
636  if (pkt.duration > 0)
637  pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
638  pkt.stream_index = video_st->index;
639 
640  // Write packet
641  error_code = av_interleaved_write_frame(oc, &pkt);
642  if (error_code < 0) {
643  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
644  }
645 
646  // Deallocate memory (if needed)
647  if (video_outbuf)
648  av_freep(&video_outbuf);
649  }
650 
651  // FLUSH AUDIO ENCODER
652  if (info.has_audio)
653  for (;;) {
654 
655  // Increment PTS (in samples and scaled to the codec's timebase)
656 #if LIBAVFORMAT_VERSION_MAJOR >= 54
657  // for some reason, it requires me to multiply channels X 2
658  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);
659 #else
660  write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
661 #endif
662 
663  AVPacket pkt;
664  av_init_packet(&pkt);
665  pkt.data = NULL;
666  pkt.size = 0;
667  pkt.pts = pkt.dts = write_audio_count;
668 
669  /* encode the image */
670  int got_packet = 0;
671  #if IS_FFMPEG_3_2
672  avcodec_send_frame(audio_codec, NULL);
673  got_packet = 0;
674  #else
675  error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
676  #endif
677  if (error_code < 0) {
678  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
679  }
680  if (!got_packet) {
681  stop_encoding = 1;
682  break;
683  }
684 
685  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
686  // but it fixes lots of PTS related issues when I do this.
687  pkt.pts = pkt.dts = write_audio_count;
688 
689  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
690  if (pkt.pts != AV_NOPTS_VALUE)
691  pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
692  if (pkt.dts != AV_NOPTS_VALUE)
693  pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
694  if (pkt.duration > 0)
695  pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
696 
697  // set stream
698  pkt.stream_index = audio_st->index;
699  pkt.flags |= AV_PKT_FLAG_KEY;
700 
701  // Write packet
702  error_code = av_interleaved_write_frame(oc, &pkt);
703  if (error_code < 0) {
704  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
705  }
706 
707  // deallocate memory for packet
708  AV_FREE_PACKET(&pkt);
709  }
710 
711 
712 }
713 
714 // Close the video codec
715 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
716 {
717  AV_FREE_CONTEXT(video_codec);
718  video_codec = NULL;
719 }
720 
721 // Close the audio codec
722 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
723 {
724  AV_FREE_CONTEXT(audio_codec);
725  audio_codec = NULL;
726 
727  // Clear buffers
728  delete[] samples;
729  delete[] audio_outbuf;
730  delete[] audio_encoder_buffer;
731  samples = NULL;
732  audio_outbuf = NULL;
733  audio_encoder_buffer = NULL;
734 
735  // Deallocate resample buffer
736  if (avr) {
737  avresample_close(avr);
738  avresample_free(&avr);
739  avr = NULL;
740  }
741 
742  if (avr_planar) {
743  avresample_close(avr_planar);
744  avresample_free(&avr_planar);
745  avr_planar = NULL;
746  }
747 }
748 
749 // Close the writer
751 {
752  // Write trailer (if needed)
753  if (!write_trailer)
754  WriteTrailer();
755 
756  // Close each codec
757  if (video_st)
758  close_video(oc, video_st);
759  if (audio_st)
760  close_audio(oc, audio_st);
761 
762  // Deallocate image scalers
763  if (image_rescalers.size() > 0)
764  RemoveScalers();
765 
766  // Free the streams
767  for (int i = 0; i < oc->nb_streams; i++) {
768  av_freep(AV_GET_CODEC_ATTRIBUTES(&oc->streams[i], &oc->streams[i]));
769  av_freep(&oc->streams[i]);
770  }
771 
772  if (!(fmt->flags & AVFMT_NOFILE)) {
773  /* close the output file */
774  avio_close(oc->pb);
775  }
776 
777  // Reset frame counters
778  write_video_count = 0;
779  write_audio_count = 0;
780 
781  // Free the context
782  av_freep(&oc);
783 
784  // Close writer
785  is_open = false;
786  prepare_streams = false;
787  write_header = false;
788  write_trailer = false;
789 
790  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::Close", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
791 }
792 
793 // Add an AVFrame to the cache
794 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
795 {
796  // Add AVFrame to map (if it does not already exist)
797  if (!av_frames.count(frame))
798  {
799  // Add av_frame
800  av_frames[frame] = av_frame;
801  }
802  else
803  {
804  // Do not add, and deallocate this AVFrame
805  AV_FREE_FRAME(&av_frame);
806  }
807 }
808 
809 // Add an audio output stream
810 AVStream* FFmpegWriter::add_audio_stream()
811 {
812  AVCodecContext *c;
813  AVStream *st;
814 
815  // Find the audio codec
816  AVCodec *codec = avcodec_find_encoder_by_name(info.acodec.c_str());
817  if (codec == NULL)
818  throw InvalidCodec("A valid audio codec could not be found for this file.", path);
819 
820  // Create a new audio stream
821  AV_FORMAT_NEW_STREAM(oc, audio_codec, codec, st)
822 
823  c->codec_id = codec->id;
824 #if LIBAVFORMAT_VERSION_MAJOR >= 53
825  c->codec_type = AVMEDIA_TYPE_AUDIO;
826 #else
827  c->codec_type = CODEC_TYPE_AUDIO;
828 #endif
829 
830  // Set the sample parameters
831  c->bit_rate = info.audio_bit_rate;
832  c->channels = info.channels;
833 
834  // Set valid sample rate (or throw error)
835  if (codec->supported_samplerates) {
836  int i;
837  for (i = 0; codec->supported_samplerates[i] != 0; i++)
838  if (info.sample_rate == codec->supported_samplerates[i])
839  {
840  // Set the valid sample rate
841  c->sample_rate = info.sample_rate;
842  break;
843  }
844  if (codec->supported_samplerates[i] == 0)
845  throw InvalidSampleRate("An invalid sample rate was detected for this codec.", path);
846  } else
847  // Set sample rate
848  c->sample_rate = info.sample_rate;
849 
850 
851  // Set a valid number of channels (or throw error)
852  int channel_layout = info.channel_layout;
853  if (codec->channel_layouts) {
854  int i;
855  for (i = 0; codec->channel_layouts[i] != 0; i++)
856  if (channel_layout == codec->channel_layouts[i])
857  {
858  // Set valid channel layout
859  c->channel_layout = channel_layout;
860  break;
861  }
862  if (codec->channel_layouts[i] == 0)
863  throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
864  } else
865  // Set valid channel layout
866  c->channel_layout = channel_layout;
867 
868  // Choose a valid sample_fmt
869  if (codec->sample_fmts) {
870  for (int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
871  {
872  // Set sample format to 1st valid format (and then exit loop)
873  c->sample_fmt = codec->sample_fmts[i];
874  break;
875  }
876  }
877  if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
878  // Default if no sample formats found
879  c->sample_fmt = AV_SAMPLE_FMT_S16;
880  }
881 
882  // some formats want stream headers to be separate
883  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
884  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
885 
887  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);
888 
889  return st;
890 }
891 
892 // Add a video output stream
893 AVStream* FFmpegWriter::add_video_stream()
894 {
895  AVCodecContext *c;
896  AVStream *st;
897 
898  // Find the video codec
899  AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
900  if (codec == NULL)
901  throw InvalidCodec("A valid video codec could not be found for this file.", path);
902 
903  // Create a new video stream
904  AV_FORMAT_NEW_STREAM(oc, video_codec, codec, st)
905 
906  c->codec_id = codec->id;
907 #if LIBAVFORMAT_VERSION_MAJOR >= 53
908  c->codec_type = AVMEDIA_TYPE_VIDEO;
909 #else
910  c->codec_type = CODEC_TYPE_VIDEO;
911 #endif
912 
913  /* Init video encoder options */
914  c->bit_rate = info.video_bit_rate;
915 
916  //TODO: Implement variable bitrate feature (which actually works). This implementation throws
917  //invalid bitrate errors and rc buffer underflow errors, etc...
918  //c->rc_min_rate = info.video_bit_rate;
919  //c->rc_max_rate = info.video_bit_rate;
920  //c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
921  //if ( !c->rc_initial_buffer_occupancy )
922  // c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
923  c->qmin = 2;
924  c->qmax = 30;
925 
926  /* resolution must be a multiple of two */
927  // TODO: require /2 height and width
928  c->width = info.width;
929  c->height = info.height;
930 
931  /* time base: this is the fundamental unit of time (in seconds) in terms
932  of which frame timestamps are represented. for fixed-fps content,
933  timebase should be 1/framerate and timestamp increments should be
934  identically 1. */
935  c->time_base.num = info.video_timebase.num;
936  c->time_base.den = info.video_timebase.den;
937  #if LIBAVFORMAT_VERSION_MAJOR >= 56
938  c->framerate = av_inv_q(c->time_base);
939  #endif
940  st->avg_frame_rate = av_inv_q(c->time_base);
941  st->time_base.num = info.video_timebase.num;
942  st->time_base.den = info.video_timebase.den;
943 
944  c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
945  c->max_b_frames = 10;
946  if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
947  /* just for testing, we also add B frames */
948  c->max_b_frames = 2;
949  if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
950  /* Needed to avoid using macroblocks in which some coeffs overflow.
951  This does not happen with normal video, it just happens here as
952  the motion of the chroma plane does not match the luma plane. */
953  c->mb_decision = 2;
954  // some formats want stream headers to be separate
955  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
956  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
957 
958  // Find all supported pixel formats for this codec
959  const PixelFormat* supported_pixel_formats = codec->pix_fmts;
960  while (supported_pixel_formats != NULL && *supported_pixel_formats != PIX_FMT_NONE) {
961  // Assign the 1st valid pixel format (if one is missing)
962  if (c->pix_fmt == PIX_FMT_NONE)
963  c->pix_fmt = *supported_pixel_formats;
964  ++supported_pixel_formats;
965  }
966 
967  // Codec doesn't have any pix formats?
968  if (c->pix_fmt == PIX_FMT_NONE) {
969  if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
970  // Raw video should use RGB24
971  c->pix_fmt = PIX_FMT_RGB24;
972 
973  if (strcmp(fmt->name, "gif") != 0)
974  // If not GIF format, skip the encoding process
975  // Set raw picture flag (so we don't encode this video)
976  oc->oformat->flags |= AVFMT_RAWPICTURE;
977  } else {
978  // Set the default codec
979  c->pix_fmt = PIX_FMT_YUV420P;
980  }
981  }
982 
984  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);
985 
986  return st;
987 }
988 
989 // open audio codec
990 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
991 {
992  AVCodec *codec;
993  AV_GET_CODEC_FROM_STREAM(st, audio_codec)
994 
995  // Set number of threads equal to number of processors (not to exceed 16)
996  audio_codec->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
997 
998  // Find the audio encoder
999  codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1000  if (!codec)
1001  codec = avcodec_find_encoder(audio_codec->codec_id);
1002  if (!codec)
1003  throw InvalidCodec("Could not find codec", path);
1004 
1005  // Init options
1006  AVDictionary *opts = NULL;
1007  av_dict_set(&opts, "strict", "experimental", 0);
1008 
1009  // Open the codec
1010  if (avcodec_open2(audio_codec, codec, &opts) < 0)
1011  throw InvalidCodec("Could not open codec", path);
1012  AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec);
1013 
1014  // Free options
1015  av_dict_free(&opts);
1016 
1017  // Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
1018  // TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
1019  if (audio_codec->frame_size <= 1) {
1020  // No frame size found... so calculate
1021  audio_input_frame_size = 50000 / info.channels;
1022 
1023  int s = AV_FIND_DECODER_CODEC_ID(st);
1024  switch (s) {
1025  case AV_CODEC_ID_PCM_S16LE:
1026  case AV_CODEC_ID_PCM_S16BE:
1027  case AV_CODEC_ID_PCM_U16LE:
1028  case AV_CODEC_ID_PCM_U16BE:
1029  audio_input_frame_size >>= 1;
1030  break;
1031  default:
1032  break;
1033  }
1034  } else {
1035  // Set frame size based on the codec
1036  audio_input_frame_size = audio_codec->frame_size;
1037  }
1038 
1039  // Set the initial frame size (since it might change during resampling)
1040  initial_audio_input_frame_size = audio_input_frame_size;
1041 
1042  // Allocate array for samples
1043  samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
1044 
1045  // Set audio output buffer (used to store the encoded audio)
1046  audio_outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
1047  audio_outbuf = new uint8_t[audio_outbuf_size];
1048 
1049  // Set audio packet encoding buffer
1050  audio_encoder_buffer_size = AUDIO_PACKET_ENCODING_SIZE;
1051  audio_encoder_buffer = new uint8_t[audio_encoder_buffer_size];
1052 
1053  // Add audio metadata (if any)
1054  for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
1055  {
1056  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1057  }
1058 
1059  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 + FF_INPUT_BUFFER_PADDING_SIZE, "", -1, "", -1, "", -1);
1060 
1061 }
1062 
1063 // open video codec
1064 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1065 {
1066  AVCodec *codec;
1067  AV_GET_CODEC_FROM_STREAM(st, video_codec)
1068 
1069  // Set number of threads equal to number of processors (not to exceed 16)
1070  video_codec->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
1071 
1072  /* find the video encoder */
1073  codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1074  if (!codec)
1075  codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
1076  if (!codec)
1077  throw InvalidCodec("Could not find codec", path);
1078 
1079  /* Force max_b_frames to 0 in some cases (i.e. for mjpeg image sequences */
1080  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)
1081  video_codec->max_b_frames = 0;
1082 
1083  // Init options
1084  AVDictionary *opts = NULL;
1085  av_dict_set(&opts, "strict", "experimental", 0);
1086 
1087  /* open the codec */
1088  if (avcodec_open2(video_codec, codec, &opts) < 0)
1089  throw InvalidCodec("Could not open codec", path);
1090  AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec);
1091 
1092  // Free options
1093  av_dict_free(&opts);
1094 
1095  // Add video metadata (if any)
1096  for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
1097  {
1098  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1099  }
1100 
1101  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video", "video_codec->thread_count", video_codec->thread_count, "", -1, "", -1, "", -1, "", -1, "", -1);
1102 
1103 }
1104 
1105 // write all queued frames' audio to the video file
1106 void FFmpegWriter::write_audio_packets(bool final)
1107 {
1108  #pragma omp task firstprivate(final)
1109  {
1110  // Init audio buffers / variables
1111  int total_frame_samples = 0;
1112  int frame_position = 0;
1113  int channels_in_frame = 0;
1114  int sample_rate_in_frame = 0;
1115  int samples_in_frame = 0;
1116  ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
1117 
1118  // Create a new array (to hold all S16 audio samples, for the current queued frames
1119  int16_t* all_queued_samples = (int16_t*)av_malloc((sizeof(int16_t)*(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE)));
1120  int16_t* all_resampled_samples = NULL;
1121  int16_t* final_samples_planar = NULL;
1122  int16_t* final_samples = NULL;
1123 
1124  // Loop through each queued audio frame
1125  while (!queued_audio_frames.empty())
1126  {
1127  // Get front frame (from the queue)
1128  std::shared_ptr<Frame> frame = queued_audio_frames.front();
1129 
1130  // Get the audio details from this frame
1131  sample_rate_in_frame = frame->SampleRate();
1132  samples_in_frame = frame->GetAudioSamplesCount();
1133  channels_in_frame = frame->GetAudioChannelsCount();
1134  channel_layout_in_frame = frame->ChannelsLayout();
1135 
1136 
1137  // Get audio sample array
1138  float* frame_samples_float = NULL;
1139  // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
1140  frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1141 
1142 
1143  // Calculate total samples
1144  total_frame_samples = samples_in_frame * channels_in_frame;
1145 
1146  // Translate audio sample values back to 16 bit integers
1147  for (int s = 0; s < total_frame_samples; s++, frame_position++)
1148  // Translate sample value and copy into buffer
1149  all_queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
1150 
1151 
1152  // Deallocate float array
1153  delete[] frame_samples_float;
1154 
1155  // Remove front item
1156  queued_audio_frames.pop_front();
1157 
1158  } // end while
1159 
1160 
1161  // Update total samples (since we've combined all queued frames)
1162  total_frame_samples = frame_position;
1163  int remaining_frame_samples = total_frame_samples;
1164  int samples_position = 0;
1165 
1166 
1167  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);
1168 
1169  // Keep track of the original sample format
1170  AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1171 
1172  AVFrame *audio_frame = NULL;
1173  if (!final) {
1174  // Create input frame (and allocate arrays)
1175  audio_frame = AV_ALLOCATE_FRAME();
1176  AV_RESET_FRAME(audio_frame);
1177  audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1178 
1179  // Fill input frame with sample data
1180  avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1181  audio_encoder_buffer_size, 0);
1182 
1183  // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
1184  switch (audio_codec->sample_fmt)
1185  {
1186  case AV_SAMPLE_FMT_FLTP:
1187  {
1188  output_sample_fmt = AV_SAMPLE_FMT_FLT;
1189  break;
1190  }
1191  case AV_SAMPLE_FMT_S32P:
1192  {
1193  output_sample_fmt = AV_SAMPLE_FMT_S32;
1194  break;
1195  }
1196  case AV_SAMPLE_FMT_S16P:
1197  {
1198  output_sample_fmt = AV_SAMPLE_FMT_S16;
1199  break;
1200  }
1201  case AV_SAMPLE_FMT_U8P:
1202  {
1203  output_sample_fmt = AV_SAMPLE_FMT_U8;
1204  break;
1205  }
1206  }
1207 
1208  // Update total samples & input frame size (due to bigger or smaller data types)
1209  total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
1210  total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
1211 
1212  // Set remaining samples
1213  remaining_frame_samples = total_frame_samples;
1214 
1215  // Create output frame (and allocate arrays)
1216  AVFrame *audio_converted = AV_ALLOCATE_FRAME();
1217  AV_RESET_FRAME(audio_converted);
1218  audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1219  av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
1220 
1221  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);
1222 
1223  // setup resample context
1224  if (!avr) {
1225  avr = avresample_alloc_context();
1226  av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
1227  av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
1228  av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1229  av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
1230  av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
1231  av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1232  av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1233  av_opt_set_int(avr, "out_channels", info.channels, 0);
1234  avresample_open(avr);
1235  }
1236  int nb_samples = 0;
1237 
1238  // Convert audio samples
1239  nb_samples = avresample_convert(avr, // audio resample context
1240  audio_converted->data, // output data pointers
1241  audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
1242  audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
1243  audio_frame->data, // input data pointers
1244  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1245  audio_frame->nb_samples); // number of input samples to convert
1246 
1247  // Create a new array (to hold all resampled S16 audio samples)
1248  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)));
1249 
1250  // Copy audio samples over original samples
1251  memcpy(all_resampled_samples, audio_converted->data[0], nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1252 
1253  // Remove converted audio
1254  av_freep(&(audio_frame->data[0]));
1255  AV_FREE_FRAME(&audio_frame);
1256  av_freep(&audio_converted->data[0]);
1257  AV_FREE_FRAME(&audio_converted);
1258  all_queued_samples = NULL; // this array cleared with above call
1259 
1260  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);
1261  }
1262 
1263  // Loop until no more samples
1264  while (remaining_frame_samples > 0 || final) {
1265  // Get remaining samples needed for this packet
1266  int remaining_packet_samples = (audio_input_frame_size * info.channels) - audio_input_position;
1267 
1268  // Determine how many samples we need
1269  int diff = 0;
1270  if (remaining_frame_samples >= remaining_packet_samples)
1271  diff = remaining_packet_samples;
1272  else if (remaining_frame_samples < remaining_packet_samples)
1273  diff = remaining_frame_samples;
1274 
1275  // Copy frame samples into the packet samples array
1276  if (!final)
1277  //TODO: Make this more sane
1278  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));
1279 
1280  // Increment counters
1281  audio_input_position += diff;
1282  samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1283  remaining_frame_samples -= diff;
1284  remaining_packet_samples -= diff;
1285 
1286  // Do we have enough samples to proceed?
1287  if (audio_input_position < (audio_input_frame_size * info.channels) && !final)
1288  // Not enough samples to encode... so wait until the next frame
1289  break;
1290 
1291  // Convert to planar (if needed by audio codec)
1292  AVFrame *frame_final = AV_ALLOCATE_FRAME();
1293  AV_RESET_FRAME(frame_final);
1294  if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1295  {
1296  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);
1297 
1298  // setup resample context
1299  if (!avr_planar) {
1300  avr_planar = avresample_alloc_context();
1301  av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
1302  av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
1303  av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
1304  av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec->sample_fmt, 0); // planar not allowed here
1305  av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
1306  av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
1307  av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1308  av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
1309  avresample_open(avr_planar);
1310  }
1311 
1312  // Create input frame (and allocate arrays)
1313  audio_frame = AV_ALLOCATE_FRAME();
1314  AV_RESET_FRAME(audio_frame);
1315  audio_frame->nb_samples = audio_input_position / info.channels;
1316 
1317  // Create a new array
1318  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)));
1319 
1320  // Copy audio into buffer for frame
1321  memcpy(final_samples_planar, samples, audio_frame->nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1322 
1323  // Fill input frame with sample data
1324  avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1325  audio_encoder_buffer_size, 0);
1326 
1327  // Create output frame (and allocate arrays)
1328  frame_final->nb_samples = audio_input_frame_size;
1329  av_samples_alloc(frame_final->data, frame_final->linesize, info.channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1330 
1331  // Convert audio samples
1332  int nb_samples = avresample_convert(avr_planar, // audio resample context
1333  frame_final->data, // output data pointers
1334  frame_final->linesize[0], // output plane size, in bytes. (0 if unknown)
1335  frame_final->nb_samples, // maximum number of samples that the output buffer can hold
1336  audio_frame->data, // input data pointers
1337  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1338  audio_frame->nb_samples); // number of input samples to convert
1339 
1340  // Copy audio samples over original samples
1341  if (nb_samples > 0)
1342  memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels);
1343 
1344  // deallocate AVFrame
1345  av_freep(&(audio_frame->data[0]));
1346  AV_FREE_FRAME(&audio_frame);
1347  all_queued_samples = NULL; // this array cleared with above call
1348 
1349  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)", "nb_samples", nb_samples, "", -1, "", -1, "", -1, "", -1, "", -1);
1350 
1351  } else {
1352  // Create a new array
1353  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))];
1354 
1355  // Copy audio into buffer for frame
1356  memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1357 
1358  // Init the nb_samples property
1359  frame_final->nb_samples = audio_input_frame_size;
1360 
1361  // Fill the final_frame AVFrame with audio (non planar)
1362  avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1363  audio_encoder_buffer_size, 0);
1364  }
1365 
1366  // Increment PTS (in samples)
1367  write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1368  frame_final->pts = write_audio_count; // Set the AVFrame's PTS
1369 
1370  // Init the packet
1371  AVPacket pkt;
1372  av_init_packet(&pkt);
1373  pkt.data = audio_encoder_buffer;
1374  pkt.size = audio_encoder_buffer_size;
1375 
1376  // Set the packet's PTS prior to encoding
1377  pkt.pts = pkt.dts = write_audio_count;
1378 
1379  /* encode the audio samples */
1380  int got_packet_ptr = 0;
1381 
1382  #if IS_FFMPEG_3_2
1383  // Encode audio (latest version of FFmpeg)
1384  int error_code;
1385  int ret = 0;
1386  int frame_finished = 0;
1387  error_code = ret = avcodec_send_frame(audio_codec, frame_final);
1388  if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1389  avcodec_send_frame(audio_codec, NULL);
1390  }
1391  else {
1392  if (ret >= 0)
1393  pkt.size = 0;
1394  ret = avcodec_receive_packet(audio_codec, &pkt);
1395  if (ret >= 0)
1396  frame_finished = 1;
1397  if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1398  avcodec_flush_buffers(audio_codec);
1399  ret = 0;
1400  }
1401  if (ret >= 0) {
1402  ret = frame_finished;
1403  }
1404  }
1405  if (!pkt.data && !frame_finished)
1406  {
1407  ret = -1;
1408  }
1409  got_packet_ptr = ret;
1410  #else
1411  // Encode audio (older versions of FFmpeg)
1412  int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1413  #endif
1414  /* if zero size, it means the image was buffered */
1415  if (error_code == 0 && got_packet_ptr) {
1416 
1417  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1418  // but it fixes lots of PTS related issues when I do this.
1419  pkt.pts = pkt.dts = write_audio_count;
1420 
1421  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
1422  if (pkt.pts != AV_NOPTS_VALUE)
1423  pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1424  if (pkt.dts != AV_NOPTS_VALUE)
1425  pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1426  if (pkt.duration > 0)
1427  pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1428 
1429  // set stream
1430  pkt.stream_index = audio_st->index;
1431  pkt.flags |= AV_PKT_FLAG_KEY;
1432 
1433  /* write the compressed frame in the media file */
1434  int error_code = av_interleaved_write_frame(oc, &pkt);
1435  if (error_code < 0)
1436  {
1437  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1438  }
1439  }
1440 
1441  if (error_code < 0)
1442  {
1443  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1444  }
1445 
1446  // deallocate AVFrame
1447  av_freep(&(frame_final->data[0]));
1448  AV_FREE_FRAME(&frame_final);
1449 
1450  // deallocate memory for packet
1451  AV_FREE_PACKET(&pkt);
1452 
1453  // Reset position
1454  audio_input_position = 0;
1455  final = false;
1456  }
1457 
1458  // Delete arrays (if needed)
1459  if (all_resampled_samples) {
1460  av_freep(&all_resampled_samples);
1461  all_resampled_samples = NULL;
1462  }
1463  if (all_queued_samples) {
1464  av_freep(&all_queued_samples);
1465  all_queued_samples = NULL;
1466  }
1467 
1468  } // end task
1469 }
1470 
1471 // Allocate an AVFrame object
1472 AVFrame* FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer)
1473 {
1474  // Create an RGB AVFrame
1475  AVFrame *new_av_frame = NULL;
1476 
1477  // Allocate an AVFrame structure
1478  new_av_frame = AV_ALLOCATE_FRAME();
1479  if (new_av_frame == NULL)
1480  throw OutOfMemory("Could not allocate AVFrame", path);
1481 
1482  // Determine required buffer size and allocate buffer
1483  *buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
1484 
1485  // Create buffer (if not provided)
1486  if (!new_buffer)
1487  {
1488  // New Buffer
1489  new_buffer = (uint8_t*)av_malloc(*buffer_size * sizeof(uint8_t));
1490  // Attach buffer to AVFrame
1491  AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
1492  new_av_frame->width = width;
1493  new_av_frame->height = height;
1494  new_av_frame->format = pix_fmt;
1495  }
1496 
1497  // return AVFrame
1498  return new_av_frame;
1499 }
1500 
1501 // process video frame
1502 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1503 {
1504  // Determine the height & width of the source image
1505  int source_image_width = frame->GetWidth();
1506  int source_image_height = frame->GetHeight();
1507 
1508  // Do nothing if size is 1x1 (i.e. no image in this frame)
1509  if (source_image_height == 1 && source_image_width == 1)
1510  return;
1511 
1512  // Init rescalers (if not initialized yet)
1513  if (image_rescalers.size() == 0)
1514  InitScalers(source_image_width, source_image_height);
1515 
1516  // Get a unique rescaler (for this thread)
1517  SwsContext *scaler = image_rescalers[rescaler_position];
1518  rescaler_position++;
1519  if (rescaler_position == num_of_rescalers)
1520  rescaler_position = 0;
1521 
1522  #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height)
1523  {
1524  // Allocate an RGB frame & final output frame
1525  int bytes_source = 0;
1526  int bytes_final = 0;
1527  AVFrame *frame_source = NULL;
1528  const uchar *pixels = NULL;
1529 
1530  // Get a list of pixels from source image
1531  pixels = frame->GetPixels();
1532 
1533  // Init AVFrame for source image & final (converted image)
1534  frame_source = allocate_avframe(PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1535  #if IS_FFMPEG_3_2
1536  AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format), info.width, info.height, &bytes_final, NULL);
1537  #else
1538  AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt, info.width, info.height, &bytes_final, NULL);
1539  #endif
1540 
1541  // Fill with data
1542  AV_COPY_PICTURE_DATA(frame_source, (uint8_t*)pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
1543  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::process_video_packet", "frame->number", frame->number, "bytes_source", bytes_source, "bytes_final", bytes_final, "", -1, "", -1, "", -1);
1544 
1545  // Resize & convert pixel format
1546  sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1547  source_image_height, frame_final->data, frame_final->linesize);
1548 
1549  // Add resized AVFrame to av_frames map
1550  #pragma omp critical (av_frames_section)
1551  add_avframe(frame, frame_final);
1552 
1553  // Deallocate memory
1554  AV_FREE_FRAME(&frame_source);
1555 
1556  } // end task
1557 
1558 }
1559 
1560 // write video frame
1561 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1562 {
1563  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);
1564 
1565  if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1566  // Raw video case.
1567  AVPacket pkt;
1568  av_init_packet(&pkt);
1569 
1570  pkt.flags |= AV_PKT_FLAG_KEY;
1571  pkt.stream_index= video_st->index;
1572  pkt.data= (uint8_t*)frame_final->data;
1573  pkt.size= sizeof(AVPicture);
1574 
1575  // Increment PTS (in frames and scaled to the codec's timebase)
1576  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
1577  pkt.pts = write_video_count;
1578 
1579  /* write the compressed frame in the media file */
1580  int error_code = av_interleaved_write_frame(oc, &pkt);
1581  if (error_code < 0)
1582  {
1583  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1584  return false;
1585  }
1586 
1587  // Deallocate packet
1588  AV_FREE_PACKET(&pkt);
1589 
1590  } else {
1591 
1592  AVPacket pkt;
1593  av_init_packet(&pkt);
1594  pkt.data = NULL;
1595  pkt.size = 0;
1596  pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1597 
1598  // Pointer for video buffer (if using old FFmpeg version)
1599  uint8_t *video_outbuf = NULL;
1600 
1601  // Increment PTS (in frames and scaled to the codec's timebase)
1602  write_video_count += av_rescale_q(1, (AVRational){info.fps.den, info.fps.num}, video_codec->time_base);
1603 
1604  // Assign the initial AVFrame PTS from the frame counter
1605  frame_final->pts = write_video_count;
1606 
1607  /* encode the image */
1608  int got_packet_ptr = 0;
1609  int error_code = 0;
1610  #if IS_FFMPEG_3_2
1611  // Write video packet (latest version of FFmpeg)
1612  int frameFinished = 0;
1613  int ret = avcodec_send_frame(video_codec, frame_final);
1614  error_code = ret;
1615  if (ret < 0 ) {
1616  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent)", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
1617  if (ret == AVERROR(EAGAIN) )
1618  cerr << "Frame EAGAIN" << "\n";
1619  if (ret == AVERROR_EOF )
1620  cerr << "Frame AVERROR_EOF" << "\n";
1621  avcodec_send_frame(video_codec, NULL);
1622  }
1623  else {
1624  while (ret >= 0) {
1625  ret = avcodec_receive_packet(video_codec, &pkt);
1626  if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1627  avcodec_flush_buffers(video_codec);
1628  got_packet_ptr = 0;
1629  break;
1630  }
1631  if (ret == 0) {
1632  got_packet_ptr = 1;
1633  break;
1634  }
1635  }
1636  }
1637  #else
1638  #if LIBAVFORMAT_VERSION_MAJOR >= 54
1639  // Write video packet (older than FFmpeg 3.2)
1640  error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1641  if (error_code != 0 )
1642  cerr << "Frame AVERROR_EOF" << "\n";
1643  if (got_packet_ptr == 0 )
1644  cerr << "Frame gotpacket error" << "\n";
1645  #else
1646  // Write video packet (even older versions of FFmpeg)
1647  int video_outbuf_size = 200000;
1648  video_outbuf = (uint8_t*) av_malloc(200000);
1649 
1650  /* encode the image */
1651  int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1652 
1653  /* if zero size, it means the image was buffered */
1654  if (out_size > 0) {
1655  if(video_codec->coded_frame->key_frame)
1656  pkt.flags |= AV_PKT_FLAG_KEY;
1657  pkt.data= video_outbuf;
1658  pkt.size= out_size;
1659 
1660  // got data back (so encode this frame)
1661  got_packet_ptr = 1;
1662  }
1663  #endif
1664  #endif
1665 
1666  /* if zero size, it means the image was buffered */
1667  if (error_code == 0 && got_packet_ptr) {
1668 
1669  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1670  // but it fixes lots of PTS related issues when I do this.
1671  //pkt.pts = pkt.dts = write_video_count;
1672 
1673  // set the timestamp
1674  if (pkt.pts != AV_NOPTS_VALUE)
1675  pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1676  if (pkt.dts != AV_NOPTS_VALUE)
1677  pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1678  if (pkt.duration > 0)
1679  pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1680  pkt.stream_index = video_st->index;
1681 
1682  /* write the compressed frame in the media file */
1683  int error_code = av_interleaved_write_frame(oc, &pkt);
1684  if (error_code < 0)
1685  {
1686  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
1687  return false;
1688  }
1689  }
1690 
1691  // Deallocate memory (if needed)
1692  if (video_outbuf)
1693  delete[] video_outbuf;
1694 
1695  // Deallocate packet
1696  AV_FREE_PACKET(&pkt);
1697  }
1698 
1699  // Success
1700  return true;
1701 }
1702 
1703 // Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
1705 {
1706  // output debug info
1707  av_dump_format(oc, 0, path.c_str(), 1);
1708 }
1709 
1710 // Init a collection of software rescalers (thread safe)
1711 void FFmpegWriter::InitScalers(int source_width, int source_height)
1712 {
1713  // Init software rescalers vector (many of them, one for each thread)
1714  for (int x = 0; x < num_of_rescalers; x++)
1715  {
1716  // Init the software scaler from FFMpeg
1717  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_BILINEAR, NULL, NULL, NULL);
1718 
1719  // Add rescaler to vector
1720  image_rescalers.push_back(img_convert_ctx);
1721  }
1722 }
1723 
1724 // Set audio resample options
1725 void FFmpegWriter::ResampleAudio(int sample_rate, int channels) {
1726  original_sample_rate = sample_rate;
1727  original_channels = channels;
1728 }
1729 
1730 // Remove & deallocate all software scalers
1732 {
1733  // Close all rescalers
1734  for (int x = 0; x < num_of_rescalers; x++)
1735  sws_freeContext(image_rescalers[x]);
1736 
1737  // Clear vector
1738  image_rescalers.clear();
1739 }
#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
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)
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
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 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 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
This namespace is the default namespace for all code in the openshot library.
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
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)