31 #include "../include/FFmpegWriter.h" 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)
71 void FFmpegWriter::auto_detect_format()
74 fmt = av_guess_format(NULL, path.c_str(), NULL);
76 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
79 oc = avformat_alloc_context();
81 throw OutOfMemory(
"Could not allocate memory for AVFormatContext.", path);
89 info.
vcodec = avcodec_find_encoder(fmt->video_codec)->name;
93 info.
acodec = avcodec_find_encoder(fmt->audio_codec)->name;
97 void FFmpegWriter::initialize_streams()
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);
106 video_st = add_video_stream();
110 audio_st = add_audio_stream();
117 if (codec.length() > 0)
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);
127 fmt->video_codec = new_codec->id;
144 if (pixel_ratio.
num > 0)
149 if (bit_rate >= 1000)
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);
175 if (codec.length() > 0)
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);
186 fmt->audio_codec = new_codec->id;
189 if (sample_rate > 7999)
198 if (original_sample_rate == 0)
200 if (original_channels == 0)
203 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetAudioOptions (" + codec +
")",
"sample_rate", sample_rate,
"channels", channels,
"bit_rate", bit_rate,
"", -1,
"", -1,
"", -1);
213 AVCodecContext *c = NULL;
214 stringstream convert(value);
221 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
224 const AVOption *option = NULL;
229 #if LIBAVFORMAT_VERSION_MAJOR <= 53 230 option = av_find_opt(c->priv_data, name.c_str(), NULL, NULL, NULL);
232 option = av_opt_find(c->priv_data, name.c_str(), NULL, 0, 0);
236 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
237 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate"))
242 convert >> c->gop_size;
244 else if (name ==
"qmin")
248 else if (name ==
"qmax")
252 else if (name ==
"max_b_frames")
254 convert >> c->max_b_frames;
256 else if (name ==
"mb_decision")
258 convert >> c->mb_decision;
260 else if (name ==
"level")
264 else if (name ==
"profile")
266 convert >> c->profile;
268 else if (name ==
"slices")
270 convert >> c->slices;
272 else if (name ==
"rc_min_rate")
274 convert >> c->rc_min_rate;
276 else if (name ==
"rc_max_rate")
278 convert >> c->rc_max_rate;
280 else if (name ==
"rc_buffer_size")
282 convert >> c->rc_buffer_size;
286 #if LIBAVFORMAT_VERSION_MAJOR <= 53 287 av_set_string3 (c->priv_data, name.c_str(), value.c_str(), 0, NULL);
289 av_opt_set (c->priv_data, name.c_str(), value.c_str(), 0);
292 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetOption (" + (
string)name +
")",
"stream == VIDEO_STREAM", stream ==
VIDEO_STREAM,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
296 throw InvalidOptions(
"The option is not valid for this codec.", path);
304 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
306 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::PrepareStreams [" + path +
"]",
"info.has_audio",
info.
has_audio,
"info.has_video",
info.
has_video,
"", -1,
"", -1,
"", -1,
"", -1);
309 initialize_streams();
313 open_video(oc, video_st);
315 open_audio(oc, audio_st);
318 prepare_streams =
true;
325 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
328 if (!(fmt->flags & AVFMT_NOFILE)) {
329 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
330 throw InvalidFile(
"Could not open or write file.", path);
334 snprintf(oc->filename,
sizeof(oc->filename),
"%s", path.c_str());
338 avformat_write_header(oc, NULL);
343 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
351 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
356 spooled_video_frames.push_back(frame);
359 spooled_audio_frames.push_back(frame);
361 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);
364 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
369 write_queued_frames();
378 write_queued_frames();
387 void FFmpegWriter::write_queued_frames()
389 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);
395 queued_video_frames = spooled_video_frames;
396 queued_audio_frames = spooled_audio_frames;
399 spooled_video_frames.clear();
400 spooled_audio_frames.clear();
405 omp_set_nested(
true);
408 bool has_error_encoding_video =
false;
415 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
416 write_audio_packets(
false);
419 while (!queued_video_frames.empty())
422 std::shared_ptr<Frame> frame = queued_video_frames.front();
425 processed_frames.push_back(frame);
429 process_video_packet(frame);
432 queued_video_frames.pop_front();
440 while (!processed_frames.empty())
443 std::shared_ptr<Frame> frame = processed_frames.front();
448 deallocate_frames.push_back(frame);
451 if (av_frames.count(frame))
454 AVFrame *frame_final = av_frames[frame];
457 bool success = write_video_packet(frame, frame_final);
459 has_error_encoding_video =
true;
464 processed_frames.pop_front();
468 while (!deallocate_frames.empty())
471 std::shared_ptr<Frame> frame = deallocate_frames.front();
474 if (av_frames.count(frame))
477 AVFrame *av_frame = av_frames[frame];
480 av_freep(&(av_frame->data[0]));
482 av_frames.erase(frame);
486 deallocate_frames.pop_front();
496 if (has_error_encoding_video)
503 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
506 for (int64_t number = start; number <= length; number++)
509 std::shared_ptr<Frame> f = reader->
GetFrame(number);
520 write_queued_frames();
524 write_audio_packets(
true);
533 av_write_trailer(oc);
536 write_trailer =
true;
538 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
542 void FFmpegWriter::flush_encoders()
544 if (
info.
has_audio && audio_codec && audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_codec->frame_size <= 1)
548 int stop_encoding = 1;
555 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
558 av_init_packet(&pkt);
563 uint8_t *video_outbuf = NULL;
569 #if LIBAVFORMAT_VERSION_MAJOR >= 54 571 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
577 int video_outbuf_size = 0;
580 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
584 if(video_codec->coded_frame->key_frame)
585 pkt.flags |= AV_PKT_FLAG_KEY;
586 pkt.data= video_outbuf;
594 if (error_code < 0) {
595 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
606 if (pkt.pts != AV_NOPTS_VALUE)
607 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
608 if (pkt.dts != AV_NOPTS_VALUE)
609 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
610 if (pkt.duration > 0)
611 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
612 pkt.stream_index = video_st->index;
615 error_code = av_interleaved_write_frame(oc, &pkt);
616 if (error_code < 0) {
617 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
622 av_freep(&video_outbuf);
630 #if LIBAVFORMAT_VERSION_MAJOR >= 54 632 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);
634 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
638 av_init_packet(&pkt);
641 pkt.pts = pkt.dts = write_audio_count;
645 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
646 if (error_code < 0) {
647 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
656 pkt.pts = pkt.dts = write_audio_count;
659 if (pkt.pts != AV_NOPTS_VALUE)
660 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
661 if (pkt.dts != AV_NOPTS_VALUE)
662 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
663 if (pkt.duration > 0)
664 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
667 pkt.stream_index = audio_st->index;
668 pkt.flags |= AV_PKT_FLAG_KEY;
671 error_code = av_interleaved_write_frame(oc, &pkt);
672 if (error_code < 0) {
673 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
684 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
686 avcodec_close(st->codec);
691 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
693 avcodec_close(st->codec);
698 delete[] audio_outbuf;
699 delete[] audio_encoder_buffer;
702 audio_encoder_buffer = NULL;
706 avresample_close(avr);
707 avresample_free(&avr);
712 avresample_close(avr_planar);
713 avresample_free(&avr_planar);
727 close_video(oc, video_st);
729 close_audio(oc, audio_st);
732 if (image_rescalers.size() > 0)
736 for (
int i = 0; i < oc->nb_streams; i++) {
737 av_freep(&oc->streams[i]->codec);
738 av_freep(&oc->streams[i]);
741 if (!(fmt->flags & AVFMT_NOFILE)) {
747 write_video_count = 0;
748 write_audio_count = 0;
755 prepare_streams =
false;
756 write_header =
false;
757 write_trailer =
false;
759 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
763 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
766 if (!av_frames.count(frame))
769 av_frames[frame] = av_frame;
779 AVStream* FFmpegWriter::add_audio_stream()
785 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
787 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
790 st = avformat_new_stream(oc, codec);
792 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
795 avcodec_get_context_defaults3(st->codec, codec);
798 c->codec_id = codec->id;
799 #if LIBAVFORMAT_VERSION_MAJOR >= 53 800 c->codec_type = AVMEDIA_TYPE_AUDIO;
802 c->codec_type = CODEC_TYPE_AUDIO;
810 if (codec->supported_samplerates) {
812 for (i = 0; codec->supported_samplerates[i] != 0; i++)
819 if (codec->supported_samplerates[i] == 0)
820 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
828 if (codec->channel_layouts) {
830 for (i = 0; codec->channel_layouts[i] != 0; i++)
831 if (channel_layout == codec->channel_layouts[i])
834 c->channel_layout = channel_layout;
837 if (codec->channel_layouts[i] == 0)
838 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
841 c->channel_layout = channel_layout;
844 if (codec->sample_fmts) {
845 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
848 c->sample_fmt = codec->sample_fmts[i];
852 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
854 c->sample_fmt = AV_SAMPLE_FMT_S16;
858 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
859 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
861 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);
867 AVStream* FFmpegWriter::add_video_stream()
873 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
875 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
878 st = avformat_new_stream(oc, codec);
880 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
883 avcodec_get_context_defaults3(st->codec, codec);
886 c->codec_id = codec->id;
887 #if LIBAVFORMAT_VERSION_MAJOR >= 53 888 c->codec_type = AVMEDIA_TYPE_VIDEO;
890 c->codec_type = CODEC_TYPE_VIDEO;
921 c->max_b_frames = 10;
922 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
925 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
931 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
932 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
935 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
936 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
939 c->pix_fmt = *supported_pixel_formats;
940 ++supported_pixel_formats;
945 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
951 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);
957 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
960 audio_codec = st->codec;
966 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
968 codec = avcodec_find_encoder(audio_codec->codec_id);
973 if (avcodec_open2(audio_codec, codec, NULL) < 0)
978 if (audio_codec->frame_size <= 1) {
982 switch (st->codec->codec_id) {
983 case AV_CODEC_ID_PCM_S16LE:
984 case AV_CODEC_ID_PCM_S16BE:
985 case AV_CODEC_ID_PCM_U16LE:
986 case AV_CODEC_ID_PCM_U16BE:
987 audio_input_frame_size >>= 1;
994 audio_input_frame_size = audio_codec->frame_size;
998 initial_audio_input_frame_size = audio_input_frame_size;
1005 audio_outbuf =
new uint8_t[audio_outbuf_size];
1009 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1011 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 + AV_INPUT_BUFFER_PADDING_SIZE,
"", -1,
"", -1,
"", -1);
1016 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1019 video_codec = st->codec;
1025 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1027 codec = avcodec_find_encoder(video_codec->codec_id);
1032 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)
1033 video_codec->max_b_frames = 0;
1036 if (avcodec_open2(video_codec, codec, NULL) < 0)
1039 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1044 void FFmpegWriter::write_audio_packets(
bool final)
1046 #pragma omp task firstprivate(final) 1049 int total_frame_samples = 0;
1050 int frame_position = 0;
1051 int channels_in_frame = 0;
1052 int sample_rate_in_frame = 0;
1053 int samples_in_frame = 0;
1058 int16_t* all_resampled_samples = NULL;
1059 int16_t* final_samples_planar = NULL;
1060 int16_t* final_samples = NULL;
1063 while (!queued_audio_frames.empty())
1066 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1069 sample_rate_in_frame = frame->SampleRate();
1070 samples_in_frame = frame->GetAudioSamplesCount();
1071 channels_in_frame = frame->GetAudioChannelsCount();
1072 channel_layout_in_frame = frame->ChannelsLayout();
1076 float* frame_samples_float = NULL;
1078 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1082 total_frame_samples = samples_in_frame * channels_in_frame;
1085 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1087 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1091 delete[] frame_samples_float;
1094 queued_audio_frames.pop_front();
1100 total_frame_samples = frame_position;
1101 int remaining_frame_samples = total_frame_samples;
1102 int samples_position = 0;
1105 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);
1108 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1110 AVFrame *audio_frame = NULL;
1115 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1118 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1119 audio_encoder_buffer_size, 0);
1122 switch (audio_codec->sample_fmt)
1124 case AV_SAMPLE_FMT_FLTP:
1126 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1129 case AV_SAMPLE_FMT_S32P:
1131 output_sample_fmt = AV_SAMPLE_FMT_S32;
1134 case AV_SAMPLE_FMT_S16P:
1136 output_sample_fmt = AV_SAMPLE_FMT_S16;
1139 case AV_SAMPLE_FMT_U8P:
1141 output_sample_fmt = AV_SAMPLE_FMT_U8;
1147 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1148 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1151 remaining_frame_samples = total_frame_samples;
1156 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1157 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1159 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);
1163 avr = avresample_alloc_context();
1164 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1166 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1167 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1168 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1170 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1172 avresample_open(avr);
1177 nb_samples = avresample_convert(avr,
1178 audio_converted->data,
1179 audio_converted->linesize[0],
1180 audio_converted->nb_samples,
1182 audio_frame->linesize[0],
1183 audio_frame->nb_samples);
1186 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)));
1189 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1192 av_freep(&(audio_frame->data[0]));
1194 av_freep(&audio_converted->data[0]);
1196 all_queued_samples = NULL;
1198 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);
1202 while (remaining_frame_samples > 0 ||
final) {
1204 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1208 if (remaining_frame_samples >= remaining_packet_samples)
1209 diff = remaining_packet_samples;
1210 else if (remaining_frame_samples < remaining_packet_samples)
1211 diff = remaining_frame_samples;
1216 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));
1219 audio_input_position += diff;
1220 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1221 remaining_frame_samples -= diff;
1222 remaining_packet_samples -= diff;
1225 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1232 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1234 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);
1238 avr_planar = avresample_alloc_context();
1241 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1242 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1245 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1246 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1247 avresample_open(avr_planar);
1253 audio_frame->nb_samples = audio_input_position /
info.
channels;
1256 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)));
1259 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1262 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1263 audio_encoder_buffer_size, 0);
1266 frame_final->nb_samples = audio_input_frame_size;
1267 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1270 int nb_samples = avresample_convert(avr_planar,
1272 frame_final->linesize[0],
1273 frame_final->nb_samples,
1275 audio_frame->linesize[0],
1276 audio_frame->nb_samples);
1280 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1283 av_freep(&(audio_frame->data[0]));
1285 all_queued_samples = NULL;
1287 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1291 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))];
1294 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1297 frame_final->nb_samples = audio_input_frame_size;
1300 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1301 audio_encoder_buffer_size, 0);
1305 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1306 frame_final->pts = write_audio_count;
1310 av_init_packet(&pkt);
1311 pkt.data = audio_encoder_buffer;
1312 pkt.size = audio_encoder_buffer_size;
1315 pkt.pts = pkt.dts = write_audio_count;
1318 int got_packet_ptr = 0;
1319 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1322 if (error_code == 0 && got_packet_ptr) {
1326 pkt.pts = pkt.dts = write_audio_count;
1329 if (pkt.pts != AV_NOPTS_VALUE)
1330 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1331 if (pkt.dts != AV_NOPTS_VALUE)
1332 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1333 if (pkt.duration > 0)
1334 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1337 pkt.stream_index = audio_st->index;
1338 pkt.flags |= AV_PKT_FLAG_KEY;
1341 int error_code = av_interleaved_write_frame(oc, &pkt);
1344 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1350 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1354 av_freep(&(frame_final->data[0]));
1361 audio_input_position = 0;
1366 if (all_resampled_samples) {
1367 av_freep(&all_resampled_samples);
1368 all_resampled_samples = NULL;
1370 if (all_queued_samples) {
1371 av_freep(&all_queued_samples);
1372 all_queued_samples = NULL;
1379 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1382 AVFrame *new_av_frame = NULL;
1386 if (new_av_frame == NULL)
1387 throw OutOfMemory(
"Could not allocate AVFrame", path);
1390 *buffer_size = avpicture_get_size(pix_fmt, width, height);
1396 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1398 avpicture_fill((AVPicture *)new_av_frame, new_buffer, pix_fmt, width, height);
1399 new_av_frame->width = width;
1400 new_av_frame->height = height;
1401 new_av_frame->format = pix_fmt;
1405 return new_av_frame;
1409 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1412 int source_image_width = frame->GetWidth();
1413 int source_image_height = frame->GetHeight();
1416 if (source_image_height == 1 && source_image_width == 1)
1420 if (image_rescalers.size() == 0)
1421 InitScalers(source_image_width, source_image_height);
1424 SwsContext *scaler = image_rescalers[rescaler_position];
1425 rescaler_position++;
1426 if (rescaler_position == num_of_rescalers)
1427 rescaler_position = 0;
1429 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1432 int bytes_source = 0;
1433 int bytes_final = 0;
1434 AVFrame *frame_source = NULL;
1435 const uchar *pixels = NULL;
1438 pixels = frame->GetPixels();
1441 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1442 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1445 avpicture_fill((AVPicture *) frame_source, (uint8_t*)pixels,
PIX_FMT_RGBA, source_image_width, source_image_height);
1446 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1449 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1450 source_image_height, frame_final->data, frame_final->linesize);
1453 #pragma omp critical (av_frames_section) 1454 add_avframe(frame, frame_final);
1464 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1466 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1469 av_init_packet(&pkt);
1472 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1475 uint8_t *video_outbuf = NULL;
1478 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1481 frame_final->pts = write_video_count;
1484 int got_packet_ptr = 0;
1486 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1488 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1494 int video_outbuf_size = 200000;
1495 video_outbuf = (uint8_t*) av_malloc(200000);
1498 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1502 if(video_codec->coded_frame->key_frame)
1503 pkt.flags |= AV_PKT_FLAG_KEY;
1504 pkt.data= video_outbuf;
1513 if (error_code == 0 && got_packet_ptr) {
1520 if (pkt.pts != AV_NOPTS_VALUE)
1521 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1522 if (pkt.dts != AV_NOPTS_VALUE)
1523 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1524 if (pkt.duration > 0)
1525 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1526 pkt.stream_index = video_st->index;
1529 int error_code = av_interleaved_write_frame(oc, &pkt);
1532 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1539 delete[] video_outbuf;
1552 av_dump_format(oc, 0, path.c_str(), 1);
1556 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1560 c = video_st->codec;
1563 for (
int x = 0; x < num_of_rescalers; x++)
1569 image_rescalers.push_back(img_convert_ctx);
1575 original_sample_rate = sample_rate;
1576 original_channels = channels;
1583 for (
int x = 0; x < num_of_rescalers; x++)
1584 sws_freeContext(image_rescalers[x]);
1587 image_rescalers.clear();
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
A video stream (used to determine which type of stream)
#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.
WriterInfo info
Information about the current media file.
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
An audio stream (used to determine which type of stream)
int video_bit_rate
The bit rate of the video stream (in bytes)
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Exception when an invalid # of audio channels are detected.
string acodec
The name of the audio codec used to encode / decode the video stream.
string vcodec
The name of the video codec used to encode / decode the video stream.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
This abstract class is the base class, used by all readers in libopenshot.
int width
The width of the video (in pixels)
int audio_bit_rate
The bit rate of the audio stream (in bytes)
#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.
Exception when invalid sample rate is detected during encoding.
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
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
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
Exception when invalid encoding options are used.
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Exception for files that can not be found or opened.
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.
This class represents a fraction.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
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.
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
bool has_video
Determines if this file has a video stream.
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
This namespace is the default namespace for all code in the openshot library.
bool has_audio
Determines if this file has an audio stream.
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.
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
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)
int den
Denominator for the fraction.
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)