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);
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;
215 stringstream convert(value);
228 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
231 const AVOption *option = NULL;
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"))
245 convert >> c->gop_size;
247 else if (name ==
"qmin")
251 else if (name ==
"qmax")
255 else if (name ==
"max_b_frames")
257 convert >> c->max_b_frames;
259 else if (name ==
"mb_decision")
261 convert >> c->mb_decision;
263 else if (name ==
"level")
267 else if (name ==
"profile")
269 convert >> c->profile;
271 else if (name ==
"slices")
273 convert >> c->slices;
275 else if (name ==
"rc_min_rate")
277 convert >> c->rc_min_rate;
279 else if (name ==
"rc_max_rate")
281 convert >> c->rc_max_rate;
283 else if (name ==
"rc_buffer_size")
285 convert >> c->rc_buffer_size;
289 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
291 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetOption (" + (
string)name +
")",
"stream == VIDEO_STREAM", stream ==
VIDEO_STREAM,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
295 throw InvalidOptions(
"The option is not valid for this codec.", path);
305 if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
315 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
317 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::PrepareStreams [" + path +
"]",
"info.has_audio",
info.
has_audio,
"info.has_video",
info.
has_video,
"", -1,
"", -1,
"", -1,
"", -1);
320 initialize_streams();
324 open_video(oc, video_st);
326 open_audio(oc, audio_st);
329 prepare_streams =
true;
336 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
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);
345 snprintf(oc->filename,
sizeof(oc->filename),
"%s", path.c_str());
353 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
356 if (avformat_write_header(oc, NULL) != 0) {
357 throw InvalidFile(
"Could not write header to file.", path);
363 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
371 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
376 spooled_video_frames.push_back(frame);
379 spooled_audio_frames.push_back(frame);
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);
384 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
389 write_queued_frames();
394 write_queued_frames();
403 void FFmpegWriter::write_queued_frames()
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);
411 queued_video_frames = spooled_video_frames;
412 queued_audio_frames = spooled_audio_frames;
415 spooled_video_frames.clear();
416 spooled_audio_frames.clear();
421 omp_set_nested(
true);
424 bool has_error_encoding_video =
false;
431 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
432 write_audio_packets(
false);
435 while (!queued_video_frames.empty())
438 std::shared_ptr<Frame> frame = queued_video_frames.front();
441 processed_frames.push_back(frame);
445 process_video_packet(frame);
448 queued_video_frames.pop_front();
456 while (!processed_frames.empty())
459 std::shared_ptr<Frame> frame = processed_frames.front();
464 deallocate_frames.push_back(frame);
467 if (av_frames.count(frame))
470 AVFrame *frame_final = av_frames[frame];
473 bool success = write_video_packet(frame, frame_final);
475 has_error_encoding_video =
true;
480 processed_frames.pop_front();
484 while (!deallocate_frames.empty())
487 std::shared_ptr<Frame> frame = deallocate_frames.front();
490 if (av_frames.count(frame))
493 AVFrame *av_frame = av_frames[frame];
496 av_freep(&(av_frame->data[0]));
498 av_frames.erase(frame);
502 deallocate_frames.pop_front();
512 if (has_error_encoding_video)
519 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
522 for (int64_t number = start; number <= length; number++)
525 std::shared_ptr<Frame> f = reader->
GetFrame(number);
536 write_queued_frames();
540 write_audio_packets(
true);
549 av_write_trailer(oc);
552 write_trailer =
true;
554 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
558 void FFmpegWriter::flush_encoders()
564 int stop_encoding = 1;
571 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
574 av_init_packet(&pkt);
579 uint8_t *video_outbuf = NULL;
586 #pragma omp critical (write_video_packet) 589 error_code = avcodec_send_frame(video_codec, NULL);
594 #if LIBAVFORMAT_VERSION_MAJOR >= 54 596 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
600 int video_outbuf_size = 0;
603 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
607 if(video_codec->coded_frame->key_frame)
608 pkt.flags |= AV_PKT_FLAG_KEY;
609 pkt.data= video_outbuf;
618 if (error_code < 0) {
619 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
630 if (pkt.pts != AV_NOPTS_VALUE)
631 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
632 if (pkt.dts != AV_NOPTS_VALUE)
633 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
634 if (pkt.duration > 0)
635 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
636 pkt.stream_index = video_st->index;
639 error_code = av_interleaved_write_frame(oc, &pkt);
640 if (error_code < 0) {
641 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
646 av_freep(&video_outbuf);
654 #if LIBAVFORMAT_VERSION_MAJOR >= 54 656 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);
658 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
662 av_init_packet(&pkt);
665 pkt.pts = pkt.dts = write_audio_count;
670 avcodec_send_frame(audio_codec, NULL);
673 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
675 if (error_code < 0) {
676 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
685 pkt.pts = pkt.dts = write_audio_count;
688 if (pkt.pts != AV_NOPTS_VALUE)
689 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
690 if (pkt.dts != AV_NOPTS_VALUE)
691 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
692 if (pkt.duration > 0)
693 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
696 pkt.stream_index = audio_st->index;
697 pkt.flags |= AV_PKT_FLAG_KEY;
700 error_code = av_interleaved_write_frame(oc, &pkt);
701 if (error_code < 0) {
702 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
713 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
720 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
727 delete[] audio_outbuf;
728 delete[] audio_encoder_buffer;
731 audio_encoder_buffer = NULL;
735 avresample_close(avr);
736 avresample_free(&avr);
741 avresample_close(avr_planar);
742 avresample_free(&avr_planar);
756 close_video(oc, video_st);
758 close_audio(oc, audio_st);
761 if (image_rescalers.size() > 0)
765 for (
int i = 0; i < oc->nb_streams; i++) {
767 av_freep(&oc->streams[i]);
770 if (!(fmt->flags & AVFMT_NOFILE)) {
776 write_video_count = 0;
777 write_audio_count = 0;
784 prepare_streams =
false;
785 write_header =
false;
786 write_trailer =
false;
788 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
792 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
795 if (!av_frames.count(frame))
798 av_frames[frame] = av_frame;
808 AVStream* FFmpegWriter::add_audio_stream()
814 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
816 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
821 c->codec_id = codec->id;
822 #if LIBAVFORMAT_VERSION_MAJOR >= 53 823 c->codec_type = AVMEDIA_TYPE_AUDIO;
825 c->codec_type = CODEC_TYPE_AUDIO;
833 if (codec->supported_samplerates) {
835 for (i = 0; codec->supported_samplerates[i] != 0; i++)
842 if (codec->supported_samplerates[i] == 0)
843 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
851 if (codec->channel_layouts) {
853 for (i = 0; codec->channel_layouts[i] != 0; i++)
854 if (channel_layout == codec->channel_layouts[i])
857 c->channel_layout = channel_layout;
860 if (codec->channel_layouts[i] == 0)
861 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
864 c->channel_layout = channel_layout;
867 if (codec->sample_fmts) {
868 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
871 c->sample_fmt = codec->sample_fmts[i];
875 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
877 c->sample_fmt = AV_SAMPLE_FMT_S16;
881 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
882 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
885 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);
891 AVStream* FFmpegWriter::add_video_stream()
897 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
899 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
904 c->codec_id = codec->id;
905 #if LIBAVFORMAT_VERSION_MAJOR >= 53 906 c->codec_type = AVMEDIA_TYPE_VIDEO;
908 c->codec_type = CODEC_TYPE_VIDEO;
935 #if LIBAVFORMAT_VERSION_MAJOR >= 56 936 c->framerate = av_inv_q(c->time_base);
938 st->avg_frame_rate = av_inv_q(c->time_base);
943 c->max_b_frames = 10;
944 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
947 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
953 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
954 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
957 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
958 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
961 c->pix_fmt = *supported_pixel_formats;
962 ++supported_pixel_formats;
967 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
974 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);
980 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
989 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
991 codec = avcodec_find_encoder(audio_codec->codec_id);
996 AVDictionary *opts = NULL;
997 av_dict_set(&opts,
"strict",
"experimental", 0);
1000 if (avcodec_open2(audio_codec, codec, &opts) < 0)
1005 av_dict_free(&opts);
1009 if (audio_codec->frame_size <= 1) {
1015 case AV_CODEC_ID_PCM_S16LE:
1016 case AV_CODEC_ID_PCM_S16BE:
1017 case AV_CODEC_ID_PCM_U16LE:
1018 case AV_CODEC_ID_PCM_U16BE:
1019 audio_input_frame_size >>= 1;
1026 audio_input_frame_size = audio_codec->frame_size;
1030 initial_audio_input_frame_size = audio_input_frame_size;
1037 audio_outbuf =
new uint8_t[audio_outbuf_size];
1041 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1046 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1049 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);
1054 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1063 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1070 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)
1071 video_codec->max_b_frames = 0;
1074 AVDictionary *opts = NULL;
1075 av_dict_set(&opts,
"strict",
"experimental", 0);
1078 if (avcodec_open2(video_codec, codec, &opts) < 0)
1083 av_dict_free(&opts);
1088 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1091 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1096 void FFmpegWriter::write_audio_packets(
bool final)
1098 #pragma omp task firstprivate(final) 1101 int total_frame_samples = 0;
1102 int frame_position = 0;
1103 int channels_in_frame = 0;
1104 int sample_rate_in_frame = 0;
1105 int samples_in_frame = 0;
1110 int16_t* all_resampled_samples = NULL;
1111 int16_t* final_samples_planar = NULL;
1112 int16_t* final_samples = NULL;
1115 while (!queued_audio_frames.empty())
1118 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1121 sample_rate_in_frame = frame->SampleRate();
1122 samples_in_frame = frame->GetAudioSamplesCount();
1123 channels_in_frame = frame->GetAudioChannelsCount();
1124 channel_layout_in_frame = frame->ChannelsLayout();
1128 float* frame_samples_float = NULL;
1130 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1134 total_frame_samples = samples_in_frame * channels_in_frame;
1137 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1139 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1143 delete[] frame_samples_float;
1146 queued_audio_frames.pop_front();
1152 total_frame_samples = frame_position;
1153 int remaining_frame_samples = total_frame_samples;
1154 int samples_position = 0;
1157 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);
1160 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1162 AVFrame *audio_frame = NULL;
1167 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1170 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1171 audio_encoder_buffer_size, 0);
1174 switch (audio_codec->sample_fmt)
1176 case AV_SAMPLE_FMT_FLTP:
1178 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1181 case AV_SAMPLE_FMT_S32P:
1183 output_sample_fmt = AV_SAMPLE_FMT_S32;
1186 case AV_SAMPLE_FMT_S16P:
1188 output_sample_fmt = AV_SAMPLE_FMT_S16;
1191 case AV_SAMPLE_FMT_U8P:
1193 output_sample_fmt = AV_SAMPLE_FMT_U8;
1199 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1200 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1203 remaining_frame_samples = total_frame_samples;
1208 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1209 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1211 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);
1215 avr = avresample_alloc_context();
1216 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1218 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1219 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1220 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1222 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1224 avresample_open(avr);
1229 nb_samples = avresample_convert(avr,
1230 audio_converted->data,
1231 audio_converted->linesize[0],
1232 audio_converted->nb_samples,
1234 audio_frame->linesize[0],
1235 audio_frame->nb_samples);
1238 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)));
1241 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1244 av_freep(&(audio_frame->data[0]));
1246 av_freep(&audio_converted->data[0]);
1248 all_queued_samples = NULL;
1250 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);
1254 while (remaining_frame_samples > 0 ||
final) {
1256 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1260 if (remaining_frame_samples >= remaining_packet_samples)
1261 diff = remaining_packet_samples;
1262 else if (remaining_frame_samples < remaining_packet_samples)
1263 diff = remaining_frame_samples;
1268 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));
1271 audio_input_position += diff;
1272 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1273 remaining_frame_samples -= diff;
1274 remaining_packet_samples -= diff;
1277 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1284 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1286 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);
1290 avr_planar = avresample_alloc_context();
1293 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1294 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1297 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1298 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1299 avresample_open(avr_planar);
1305 audio_frame->nb_samples = audio_input_position /
info.
channels;
1308 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)));
1311 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1314 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1315 audio_encoder_buffer_size, 0);
1318 frame_final->nb_samples = audio_input_frame_size;
1319 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1322 int nb_samples = avresample_convert(avr_planar,
1324 frame_final->linesize[0],
1325 frame_final->nb_samples,
1327 audio_frame->linesize[0],
1328 audio_frame->nb_samples);
1332 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1335 av_freep(&(audio_frame->data[0]));
1337 all_queued_samples = NULL;
1339 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1343 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))];
1346 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1349 frame_final->nb_samples = audio_input_frame_size;
1352 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1353 audio_encoder_buffer_size, 0);
1357 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1358 frame_final->pts = write_audio_count;
1362 av_init_packet(&pkt);
1363 pkt.data = audio_encoder_buffer;
1364 pkt.size = audio_encoder_buffer_size;
1367 pkt.pts = pkt.dts = write_audio_count;
1370 int got_packet_ptr = 0;
1376 int frame_finished = 0;
1377 error_code = ret = avcodec_send_frame(audio_codec, frame_final);
1378 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1379 avcodec_send_frame(audio_codec, NULL);
1384 ret = avcodec_receive_packet(audio_codec, &pkt);
1387 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1388 avcodec_flush_buffers(audio_codec);
1392 ret = frame_finished;
1395 if (!pkt.data && !frame_finished)
1399 got_packet_ptr = ret;
1402 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1405 if (error_code == 0 && got_packet_ptr) {
1409 pkt.pts = pkt.dts = write_audio_count;
1412 if (pkt.pts != AV_NOPTS_VALUE)
1413 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1414 if (pkt.dts != AV_NOPTS_VALUE)
1415 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1416 if (pkt.duration > 0)
1417 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1420 pkt.stream_index = audio_st->index;
1421 pkt.flags |= AV_PKT_FLAG_KEY;
1424 int error_code = av_interleaved_write_frame(oc, &pkt);
1427 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1433 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1437 av_freep(&(frame_final->data[0]));
1444 audio_input_position = 0;
1449 if (all_resampled_samples) {
1450 av_freep(&all_resampled_samples);
1451 all_resampled_samples = NULL;
1453 if (all_queued_samples) {
1454 av_freep(&all_queued_samples);
1455 all_queued_samples = NULL;
1462 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1465 AVFrame *new_av_frame = NULL;
1469 if (new_av_frame == NULL)
1470 throw OutOfMemory(
"Could not allocate AVFrame", path);
1479 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1482 new_av_frame->width = width;
1483 new_av_frame->height = height;
1484 new_av_frame->format = pix_fmt;
1488 return new_av_frame;
1492 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1495 int source_image_width = frame->GetWidth();
1496 int source_image_height = frame->GetHeight();
1499 if (source_image_height == 1 && source_image_width == 1)
1503 if (image_rescalers.size() == 0)
1504 InitScalers(source_image_width, source_image_height);
1507 SwsContext *scaler = image_rescalers[rescaler_position];
1508 rescaler_position++;
1509 if (rescaler_position == num_of_rescalers)
1510 rescaler_position = 0;
1512 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1515 int bytes_source = 0;
1516 int bytes_final = 0;
1517 AVFrame *frame_source = NULL;
1518 const uchar *pixels = NULL;
1521 pixels = frame->GetPixels();
1524 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1526 AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format),
info.
width,
info.
height, &bytes_final, NULL);
1528 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1533 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1536 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1537 source_image_height, frame_final->data, frame_final->linesize);
1540 #pragma omp critical (av_frames_section) 1541 add_avframe(frame, frame_final);
1551 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1553 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1556 av_init_packet(&pkt);
1559 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1562 uint8_t *video_outbuf = NULL;
1565 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1568 frame_final->pts = write_video_count;
1571 int got_packet_ptr = 0;
1575 int frameFinished = 0;
1576 int ret = avcodec_send_frame(video_codec, frame_final);
1579 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet (Frame not sent)",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1580 if (ret == AVERROR(EAGAIN) )
1581 cerr <<
"Frame EAGAIN" <<
"\n";
1582 if (ret == AVERROR_EOF )
1583 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1584 avcodec_send_frame(video_codec, NULL);
1588 ret = avcodec_receive_packet(video_codec, &pkt);
1589 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1590 avcodec_flush_buffers(video_codec);
1601 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1603 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1604 if (error_code != 0 )
1605 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1606 if (got_packet_ptr == 0 )
1607 cerr <<
"Frame gotpacket error" <<
"\n";
1610 int video_outbuf_size = 200000;
1611 video_outbuf = (uint8_t*) av_malloc(200000);
1614 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1618 if(video_codec->coded_frame->key_frame)
1619 pkt.flags |= AV_PKT_FLAG_KEY;
1620 pkt.data= video_outbuf;
1630 if (error_code == 0 && got_packet_ptr) {
1637 if (pkt.pts != AV_NOPTS_VALUE)
1638 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1639 if (pkt.dts != AV_NOPTS_VALUE)
1640 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1641 if (pkt.duration > 0)
1642 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1643 pkt.stream_index = video_st->index;
1646 int error_code = av_interleaved_write_frame(oc, &pkt);
1649 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1656 delete[] video_outbuf;
1669 av_dump_format(oc, 0, path.c_str(), 1);
1673 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1676 for (
int x = 0; x < num_of_rescalers; x++)
1679 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);
1682 image_rescalers.push_back(img_convert_ctx);
1688 original_sample_rate = sample_rate;
1689 original_channels = channels;
1696 for (
int x = 0; x < num_of_rescalers; x++)
1697 sws_freeContext(image_rescalers[x]);
1700 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)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
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.
#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.
string acodec
The name of the audio codec used to encode / decode the video stream.
#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.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
#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.
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
#define AV_FREE_CONTEXT(av_context)
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
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.
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) ...
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)
#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.
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.
#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.
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 AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st)
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)
#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)