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()
566 int stop_encoding = 1;
573 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
576 av_init_packet(&pkt);
581 uint8_t *video_outbuf = NULL;
588 #pragma omp critical (write_video_packet) 591 error_code = avcodec_send_frame(video_codec, NULL);
596 #if LIBAVFORMAT_VERSION_MAJOR >= 54 598 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
602 int video_outbuf_size = 0;
605 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
609 if(video_codec->coded_frame->key_frame)
610 pkt.flags |= AV_PKT_FLAG_KEY;
611 pkt.data= video_outbuf;
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);
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;
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);
648 av_freep(&video_outbuf);
656 #if LIBAVFORMAT_VERSION_MAJOR >= 54 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);
660 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
664 av_init_packet(&pkt);
667 pkt.pts = pkt.dts = write_audio_count;
672 avcodec_send_frame(audio_codec, NULL);
675 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
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);
687 pkt.pts = pkt.dts = write_audio_count;
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);
698 pkt.stream_index = audio_st->index;
699 pkt.flags |= AV_PKT_FLAG_KEY;
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);
715 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
722 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
729 delete[] audio_outbuf;
730 delete[] audio_encoder_buffer;
733 audio_encoder_buffer = NULL;
737 avresample_close(avr);
738 avresample_free(&avr);
743 avresample_close(avr_planar);
744 avresample_free(&avr_planar);
758 close_video(oc, video_st);
760 close_audio(oc, audio_st);
763 if (image_rescalers.size() > 0)
767 for (
int i = 0; i < oc->nb_streams; i++) {
769 av_freep(&oc->streams[i]);
772 if (!(fmt->flags & AVFMT_NOFILE)) {
778 write_video_count = 0;
779 write_audio_count = 0;
786 prepare_streams =
false;
787 write_header =
false;
788 write_trailer =
false;
790 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
794 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
797 if (!av_frames.count(frame))
800 av_frames[frame] = av_frame;
810 AVStream* FFmpegWriter::add_audio_stream()
816 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
818 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
823 c->codec_id = codec->id;
824 #if LIBAVFORMAT_VERSION_MAJOR >= 53 825 c->codec_type = AVMEDIA_TYPE_AUDIO;
827 c->codec_type = CODEC_TYPE_AUDIO;
835 if (codec->supported_samplerates) {
837 for (i = 0; codec->supported_samplerates[i] != 0; i++)
844 if (codec->supported_samplerates[i] == 0)
845 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
853 if (codec->channel_layouts) {
855 for (i = 0; codec->channel_layouts[i] != 0; i++)
856 if (channel_layout == codec->channel_layouts[i])
859 c->channel_layout = channel_layout;
862 if (codec->channel_layouts[i] == 0)
863 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
866 c->channel_layout = channel_layout;
869 if (codec->sample_fmts) {
870 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
873 c->sample_fmt = codec->sample_fmts[i];
877 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
879 c->sample_fmt = AV_SAMPLE_FMT_S16;
883 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
884 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
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);
893 AVStream* FFmpegWriter::add_video_stream()
899 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
901 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
906 c->codec_id = codec->id;
907 #if LIBAVFORMAT_VERSION_MAJOR >= 53 908 c->codec_type = AVMEDIA_TYPE_VIDEO;
910 c->codec_type = CODEC_TYPE_VIDEO;
937 #if LIBAVFORMAT_VERSION_MAJOR >= 56 938 c->framerate = av_inv_q(c->time_base);
940 st->avg_frame_rate = av_inv_q(c->time_base);
945 c->max_b_frames = 10;
946 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
949 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
955 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
956 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
959 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
960 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
963 c->pix_fmt = *supported_pixel_formats;
964 ++supported_pixel_formats;
969 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
973 if (strcmp(fmt->name,
"gif") != 0)
976 oc->oformat->flags |= AVFMT_RAWPICTURE;
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);
990 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
999 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1001 codec = avcodec_find_encoder(audio_codec->codec_id);
1006 AVDictionary *opts = NULL;
1007 av_dict_set(&opts,
"strict",
"experimental", 0);
1010 if (avcodec_open2(audio_codec, codec, &opts) < 0)
1015 av_dict_free(&opts);
1019 if (audio_codec->frame_size <= 1) {
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;
1036 audio_input_frame_size = audio_codec->frame_size;
1040 initial_audio_input_frame_size = audio_input_frame_size;
1047 audio_outbuf =
new uint8_t[audio_outbuf_size];
1051 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1056 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
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);
1064 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1073 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
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;
1084 AVDictionary *opts = NULL;
1085 av_dict_set(&opts,
"strict",
"experimental", 0);
1088 if (avcodec_open2(video_codec, codec, &opts) < 0)
1093 av_dict_free(&opts);
1098 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1101 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1106 void FFmpegWriter::write_audio_packets(
bool final)
1108 #pragma omp task firstprivate(final) 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;
1120 int16_t* all_resampled_samples = NULL;
1121 int16_t* final_samples_planar = NULL;
1122 int16_t* final_samples = NULL;
1125 while (!queued_audio_frames.empty())
1128 std::shared_ptr<Frame> frame = queued_audio_frames.front();
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();
1138 float* frame_samples_float = NULL;
1140 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1144 total_frame_samples = samples_in_frame * channels_in_frame;
1147 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1149 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1153 delete[] frame_samples_float;
1156 queued_audio_frames.pop_front();
1162 total_frame_samples = frame_position;
1163 int remaining_frame_samples = total_frame_samples;
1164 int samples_position = 0;
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);
1170 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1172 AVFrame *audio_frame = NULL;
1177 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
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);
1184 switch (audio_codec->sample_fmt)
1186 case AV_SAMPLE_FMT_FLTP:
1188 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1191 case AV_SAMPLE_FMT_S32P:
1193 output_sample_fmt = AV_SAMPLE_FMT_S32;
1196 case AV_SAMPLE_FMT_S16P:
1198 output_sample_fmt = AV_SAMPLE_FMT_S16;
1201 case AV_SAMPLE_FMT_U8P:
1203 output_sample_fmt = AV_SAMPLE_FMT_U8;
1209 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1210 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1213 remaining_frame_samples = total_frame_samples;
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);
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);
1225 avr = avresample_alloc_context();
1226 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 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);
1230 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1232 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1234 avresample_open(avr);
1239 nb_samples = avresample_convert(avr,
1240 audio_converted->data,
1241 audio_converted->linesize[0],
1242 audio_converted->nb_samples,
1244 audio_frame->linesize[0],
1245 audio_frame->nb_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)));
1251 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1254 av_freep(&(audio_frame->data[0]));
1256 av_freep(&audio_converted->data[0]);
1258 all_queued_samples = NULL;
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);
1264 while (remaining_frame_samples > 0 ||
final) {
1266 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
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;
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));
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;
1287 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1294 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
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);
1300 avr_planar = avresample_alloc_context();
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);
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);
1315 audio_frame->nb_samples = audio_input_position /
info.
channels;
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)));
1321 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1324 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1325 audio_encoder_buffer_size, 0);
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);
1332 int nb_samples = avresample_convert(avr_planar,
1334 frame_final->linesize[0],
1335 frame_final->nb_samples,
1337 audio_frame->linesize[0],
1338 audio_frame->nb_samples);
1342 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1345 av_freep(&(audio_frame->data[0]));
1347 all_queued_samples = NULL;
1349 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
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))];
1356 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1359 frame_final->nb_samples = audio_input_frame_size;
1362 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1363 audio_encoder_buffer_size, 0);
1367 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1368 frame_final->pts = write_audio_count;
1372 av_init_packet(&pkt);
1373 pkt.data = audio_encoder_buffer;
1374 pkt.size = audio_encoder_buffer_size;
1377 pkt.pts = pkt.dts = write_audio_count;
1380 int got_packet_ptr = 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);
1394 ret = avcodec_receive_packet(audio_codec, &pkt);
1397 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1398 avcodec_flush_buffers(audio_codec);
1402 ret = frame_finished;
1405 if (!pkt.data && !frame_finished)
1409 got_packet_ptr = ret;
1412 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1415 if (error_code == 0 && got_packet_ptr) {
1419 pkt.pts = pkt.dts = write_audio_count;
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);
1430 pkt.stream_index = audio_st->index;
1431 pkt.flags |= AV_PKT_FLAG_KEY;
1434 int error_code = av_interleaved_write_frame(oc, &pkt);
1437 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1443 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1447 av_freep(&(frame_final->data[0]));
1454 audio_input_position = 0;
1459 if (all_resampled_samples) {
1460 av_freep(&all_resampled_samples);
1461 all_resampled_samples = NULL;
1463 if (all_queued_samples) {
1464 av_freep(&all_queued_samples);
1465 all_queued_samples = NULL;
1472 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1475 AVFrame *new_av_frame = NULL;
1479 if (new_av_frame == NULL)
1480 throw OutOfMemory(
"Could not allocate AVFrame", path);
1489 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1492 new_av_frame->width = width;
1493 new_av_frame->height = height;
1494 new_av_frame->format = pix_fmt;
1498 return new_av_frame;
1502 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1505 int source_image_width = frame->GetWidth();
1506 int source_image_height = frame->GetHeight();
1509 if (source_image_height == 1 && source_image_width == 1)
1513 if (image_rescalers.size() == 0)
1514 InitScalers(source_image_width, source_image_height);
1517 SwsContext *scaler = image_rescalers[rescaler_position];
1518 rescaler_position++;
1519 if (rescaler_position == num_of_rescalers)
1520 rescaler_position = 0;
1522 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1525 int bytes_source = 0;
1526 int bytes_final = 0;
1527 AVFrame *frame_source = NULL;
1528 const uchar *pixels = NULL;
1531 pixels = frame->GetPixels();
1534 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1536 AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format),
info.
width,
info.
height, &bytes_final, NULL);
1538 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1543 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1546 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1547 source_image_height, frame_final->data, frame_final->linesize);
1550 #pragma omp critical (av_frames_section) 1551 add_avframe(frame, frame_final);
1561 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
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);
1565 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1568 av_init_packet(&pkt);
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);
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;
1580 int error_code = av_interleaved_write_frame(oc, &pkt);
1583 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1593 av_init_packet(&pkt);
1596 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1599 uint8_t *video_outbuf = NULL;
1602 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1605 frame_final->pts = write_video_count;
1608 int got_packet_ptr = 0;
1612 int frameFinished = 0;
1613 int ret = avcodec_send_frame(video_codec, frame_final);
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);
1625 ret = avcodec_receive_packet(video_codec, &pkt);
1626 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1627 avcodec_flush_buffers(video_codec);
1638 #if LIBAVFORMAT_VERSION_MAJOR >= 54 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";
1647 int video_outbuf_size = 200000;
1648 video_outbuf = (uint8_t*) av_malloc(200000);
1651 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1655 if(video_codec->coded_frame->key_frame)
1656 pkt.flags |= AV_PKT_FLAG_KEY;
1657 pkt.data= video_outbuf;
1667 if (error_code == 0 && got_packet_ptr) {
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;
1683 int error_code = av_interleaved_write_frame(oc, &pkt);
1686 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1693 delete[] video_outbuf;
1707 av_dump_format(oc, 0, path.c_str(), 1);
1711 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1714 for (
int x = 0; x < num_of_rescalers; x++)
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);
1720 image_rescalers.push_back(img_convert_ctx);
1726 original_sample_rate = sample_rate;
1727 original_channels = channels;
1734 for (
int x = 0; x < num_of_rescalers; x++)
1735 sws_freeContext(image_rescalers[x]);
1738 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)