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->AV_FILENAME,
sizeof(oc->AV_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()
562 #if (LIBAVFORMAT_VERSION_MAJOR < 58) 568 int stop_encoding = 1;
575 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
578 av_init_packet(&pkt);
583 uint8_t *video_outbuf = NULL;
590 #pragma omp critical (write_video_packet) 593 error_code = avcodec_send_frame(video_codec, NULL);
595 while (error_code >= 0) {
596 error_code = avcodec_receive_packet(video_codec, &pkt);
597 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
600 avcodec_flush_buffers(video_codec);
603 if (pkt.pts != AV_NOPTS_VALUE)
604 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
605 if (pkt.dts != AV_NOPTS_VALUE)
606 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
607 if (pkt.duration > 0)
608 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
609 pkt.stream_index = video_st->index;
610 error_code = av_interleaved_write_frame(oc, &pkt);
615 #if LIBAVFORMAT_VERSION_MAJOR >= 54 617 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
621 int video_outbuf_size = 0;
624 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
628 if(video_codec->coded_frame->key_frame)
629 pkt.flags |= AV_PKT_FLAG_KEY;
630 pkt.data= video_outbuf;
639 if (error_code < 0) {
640 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
651 if (pkt.pts != AV_NOPTS_VALUE)
652 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
653 if (pkt.dts != AV_NOPTS_VALUE)
654 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
655 if (pkt.duration > 0)
656 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
657 pkt.stream_index = video_st->index;
660 error_code = av_interleaved_write_frame(oc, &pkt);
661 if (error_code < 0) {
662 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
667 av_freep(&video_outbuf);
675 #if LIBAVFORMAT_VERSION_MAJOR >= 54 677 write_audio_count += av_rescale_q(audio_input_position / (audio_codec->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)), (AVRational){1,
info.
sample_rate}, audio_codec->time_base);
679 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
683 av_init_packet(&pkt);
686 pkt.pts = pkt.dts = write_audio_count;
691 avcodec_send_frame(audio_codec, NULL);
694 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
696 if (error_code < 0) {
697 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
706 pkt.pts = pkt.dts = write_audio_count;
709 if (pkt.pts != AV_NOPTS_VALUE)
710 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
711 if (pkt.dts != AV_NOPTS_VALUE)
712 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
713 if (pkt.duration > 0)
714 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
717 pkt.stream_index = audio_st->index;
718 pkt.flags |= AV_PKT_FLAG_KEY;
721 error_code = av_interleaved_write_frame(oc, &pkt);
722 if (error_code < 0) {
723 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
734 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
741 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
748 delete[] audio_outbuf;
749 delete[] audio_encoder_buffer;
752 audio_encoder_buffer = NULL;
777 close_video(oc, video_st);
779 close_audio(oc, audio_st);
782 if (image_rescalers.size() > 0)
786 for (
int i = 0; i < oc->nb_streams; i++) {
788 av_freep(&oc->streams[i]);
791 if (!(fmt->flags & AVFMT_NOFILE)) {
797 write_video_count = 0;
798 write_audio_count = 0;
805 prepare_streams =
false;
806 write_header =
false;
807 write_trailer =
false;
809 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
813 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
816 if (!av_frames.count(frame))
819 av_frames[frame] = av_frame;
829 AVStream* FFmpegWriter::add_audio_stream()
835 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
837 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
842 c->codec_id = codec->id;
843 #if LIBAVFORMAT_VERSION_MAJOR >= 53 844 c->codec_type = AVMEDIA_TYPE_AUDIO;
846 c->codec_type = CODEC_TYPE_AUDIO;
854 if (codec->supported_samplerates) {
856 for (i = 0; codec->supported_samplerates[i] != 0; i++)
863 if (codec->supported_samplerates[i] == 0)
864 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
872 if (codec->channel_layouts) {
874 for (i = 0; codec->channel_layouts[i] != 0; i++)
875 if (channel_layout == codec->channel_layouts[i])
878 c->channel_layout = channel_layout;
881 if (codec->channel_layouts[i] == 0)
882 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
885 c->channel_layout = channel_layout;
888 if (codec->sample_fmts) {
889 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
892 c->sample_fmt = codec->sample_fmts[i];
896 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
898 c->sample_fmt = AV_SAMPLE_FMT_S16;
902 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
903 #if (LIBAVCODEC_VERSION_MAJOR >= 57) 904 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
906 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
910 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_audio_stream",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->channels", c->channels,
"c->sample_fmt", c->sample_fmt,
"c->channel_layout", c->channel_layout,
"c->sample_rate", c->sample_rate);
916 AVStream* FFmpegWriter::add_video_stream()
922 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
924 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
929 c->codec_id = codec->id;
930 #if LIBAVFORMAT_VERSION_MAJOR >= 53 931 c->codec_type = AVMEDIA_TYPE_VIDEO;
933 c->codec_type = CODEC_TYPE_VIDEO;
960 #if LIBAVFORMAT_VERSION_MAJOR >= 56 961 c->framerate = av_inv_q(c->time_base);
963 st->avg_frame_rate = av_inv_q(c->time_base);
968 c->max_b_frames = 10;
969 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
972 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
978 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
979 #if (LIBAVCODEC_VERSION_MAJOR >= 57) 980 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
982 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
986 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
987 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
990 c->pix_fmt = *supported_pixel_formats;
991 ++supported_pixel_formats;
996 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
1000 #if (LIBAVFORMAT_VERSION_MAJOR < 58) 1001 if (strcmp(fmt->name,
"gif") != 0)
1004 oc->oformat->flags |= AVFMT_RAWPICTURE;
1013 #if (LIBAVFORMAT_VERSION_MAJOR < 58) 1014 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_video_stream (" + (
string)fmt->name +
" : " + (
string)av_get_pix_fmt_name(c->pix_fmt) +
")",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->pix_fmt", c->pix_fmt,
"oc->oformat->flags", oc->oformat->flags,
"AVFMT_RAWPICTURE", AVFMT_RAWPICTURE,
"", -1);
1016 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_video_stream (" + (
string)fmt->name +
" : " + (
string)av_get_pix_fmt_name(c->pix_fmt) +
")",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->pix_fmt", c->pix_fmt,
"oc->oformat->flags", oc->oformat->flags,
"", -1,
"", -1);
1023 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
1032 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1034 codec = avcodec_find_encoder(audio_codec->codec_id);
1039 AVDictionary *opts = NULL;
1040 av_dict_set(&opts,
"strict",
"experimental", 0);
1043 if (avcodec_open2(audio_codec, codec, &opts) < 0)
1048 av_dict_free(&opts);
1052 if (audio_codec->frame_size <= 1) {
1058 case AV_CODEC_ID_PCM_S16LE:
1059 case AV_CODEC_ID_PCM_S16BE:
1060 case AV_CODEC_ID_PCM_U16LE:
1061 case AV_CODEC_ID_PCM_U16BE:
1062 audio_input_frame_size >>= 1;
1069 audio_input_frame_size = audio_codec->frame_size;
1073 initial_audio_input_frame_size = audio_input_frame_size;
1080 audio_outbuf =
new uint8_t[audio_outbuf_size];
1084 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1089 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1092 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_audio",
"audio_codec->thread_count", audio_codec->thread_count,
"audio_input_frame_size", audio_input_frame_size,
"buffer_size",
AVCODEC_MAX_AUDIO_FRAME_SIZE +
MY_INPUT_BUFFER_PADDING_SIZE,
"", -1,
"", -1,
"", -1);
1097 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1106 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1113 if(video_codec->max_b_frames && video_codec->codec_id != AV_CODEC_ID_MPEG4 && video_codec->codec_id != AV_CODEC_ID_MPEG1VIDEO && video_codec->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1114 video_codec->max_b_frames = 0;
1117 AVDictionary *opts = NULL;
1118 av_dict_set(&opts,
"strict",
"experimental", 0);
1121 if (avcodec_open2(video_codec, codec, &opts) < 0)
1126 av_dict_free(&opts);
1131 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1134 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1139 void FFmpegWriter::write_audio_packets(
bool final)
1141 #pragma omp task firstprivate(final) 1144 int total_frame_samples = 0;
1145 int frame_position = 0;
1146 int channels_in_frame = 0;
1147 int sample_rate_in_frame = 0;
1148 int samples_in_frame = 0;
1153 int16_t* all_resampled_samples = NULL;
1154 int16_t* final_samples_planar = NULL;
1155 int16_t* final_samples = NULL;
1158 while (!queued_audio_frames.empty())
1161 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1164 sample_rate_in_frame = frame->SampleRate();
1165 samples_in_frame = frame->GetAudioSamplesCount();
1166 channels_in_frame = frame->GetAudioChannelsCount();
1167 channel_layout_in_frame = frame->ChannelsLayout();
1171 float* frame_samples_float = NULL;
1173 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1177 total_frame_samples = samples_in_frame * channels_in_frame;
1180 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1182 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1186 delete[] frame_samples_float;
1189 queued_audio_frames.pop_front();
1195 total_frame_samples = frame_position;
1196 int remaining_frame_samples = total_frame_samples;
1197 int samples_position = 0;
1200 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets",
"final",
final,
"total_frame_samples", total_frame_samples,
"channel_layout_in_frame", channel_layout_in_frame,
"channels_in_frame", channels_in_frame,
"samples_in_frame", samples_in_frame,
"LAYOUT_MONO",
LAYOUT_MONO);
1203 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1205 AVFrame *audio_frame = NULL;
1210 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1213 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1214 audio_encoder_buffer_size, 0);
1217 switch (audio_codec->sample_fmt)
1219 case AV_SAMPLE_FMT_FLTP:
1221 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1224 case AV_SAMPLE_FMT_S32P:
1226 output_sample_fmt = AV_SAMPLE_FMT_S32;
1229 case AV_SAMPLE_FMT_S16P:
1231 output_sample_fmt = AV_SAMPLE_FMT_S16;
1234 case AV_SAMPLE_FMT_U8P:
1236 output_sample_fmt = AV_SAMPLE_FMT_U8;
1242 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1243 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1246 remaining_frame_samples = total_frame_samples;
1251 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1252 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1254 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (1st resampling)",
"in_sample_fmt", AV_SAMPLE_FMT_S16,
"out_sample_fmt", output_sample_fmt,
"in_sample_rate", sample_rate_in_frame,
"out_sample_rate",
info.
sample_rate,
"in_channels", channels_in_frame,
"out_channels",
info.
channels);
1259 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1261 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1262 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1263 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1265 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1273 audio_converted->data,
1274 audio_converted->linesize[0],
1275 audio_converted->nb_samples,
1277 audio_frame->linesize[0],
1278 audio_frame->nb_samples);
1281 all_resampled_samples = (int16_t*)av_malloc(
sizeof(int16_t) * nb_samples *
info.
channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1284 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1287 av_freep(&(audio_frame->data[0]));
1289 av_freep(&audio_converted->data[0]);
1291 all_queued_samples = NULL;
1293 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
"nb_samples", nb_samples,
"remaining_frame_samples", remaining_frame_samples,
"", -1,
"", -1,
"", -1,
"", -1);
1297 while (remaining_frame_samples > 0 ||
final) {
1299 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1303 if (remaining_frame_samples >= remaining_packet_samples)
1304 diff = remaining_packet_samples;
1305 else if (remaining_frame_samples < remaining_packet_samples)
1306 diff = remaining_frame_samples;
1311 memcpy(samples + (audio_input_position * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))), all_resampled_samples + samples_position, diff * av_get_bytes_per_sample(output_sample_fmt));
1314 audio_input_position += diff;
1315 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1316 remaining_frame_samples -= diff;
1317 remaining_packet_samples -= diff;
1320 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1327 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1329 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
"in_sample_fmt", output_sample_fmt,
"out_sample_fmt", audio_codec->sample_fmt,
"in_sample_rate",
info.
sample_rate,
"out_sample_rate",
info.
sample_rate,
"in_channels",
info.
channels,
"out_channels",
info.
channels);
1336 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1337 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1340 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1341 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1348 audio_frame->nb_samples = audio_input_position /
info.
channels;
1351 final_samples_planar = (int16_t*)av_malloc(
sizeof(int16_t) * audio_frame->nb_samples *
info.
channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1354 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1357 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1358 audio_encoder_buffer_size, 0);
1361 frame_final->nb_samples = audio_input_frame_size;
1362 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1367 frame_final->linesize[0],
1368 frame_final->nb_samples,
1370 audio_frame->linesize[0],
1371 audio_frame->nb_samples);
1375 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1378 av_freep(&(audio_frame->data[0]));
1380 all_queued_samples = NULL;
1382 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1386 final_samples =
new int16_t[audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))];
1389 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1392 frame_final->nb_samples = audio_input_frame_size;
1395 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1396 audio_encoder_buffer_size, 0);
1400 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1401 frame_final->pts = write_audio_count;
1405 av_init_packet(&pkt);
1406 pkt.data = audio_encoder_buffer;
1407 pkt.size = audio_encoder_buffer_size;
1410 pkt.pts = pkt.dts = write_audio_count;
1413 int got_packet_ptr = 0;
1419 int frame_finished = 0;
1420 error_code = ret = avcodec_send_frame(audio_codec, frame_final);
1421 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1422 avcodec_send_frame(audio_codec, NULL);
1427 ret = avcodec_receive_packet(audio_codec, &pkt);
1430 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1431 avcodec_flush_buffers(audio_codec);
1435 ret = frame_finished;
1438 if (!pkt.data && !frame_finished)
1442 got_packet_ptr = ret;
1445 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1448 if (error_code == 0 && got_packet_ptr) {
1452 pkt.pts = pkt.dts = write_audio_count;
1455 if (pkt.pts != AV_NOPTS_VALUE)
1456 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1457 if (pkt.dts != AV_NOPTS_VALUE)
1458 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1459 if (pkt.duration > 0)
1460 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1463 pkt.stream_index = audio_st->index;
1464 pkt.flags |= AV_PKT_FLAG_KEY;
1467 int error_code = av_interleaved_write_frame(oc, &pkt);
1470 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1476 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1480 av_freep(&(frame_final->data[0]));
1487 audio_input_position = 0;
1492 if (all_resampled_samples) {
1493 av_freep(&all_resampled_samples);
1494 all_resampled_samples = NULL;
1496 if (all_queued_samples) {
1497 av_freep(&all_queued_samples);
1498 all_queued_samples = NULL;
1505 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1508 AVFrame *new_av_frame = NULL;
1512 if (new_av_frame == NULL)
1513 throw OutOfMemory(
"Could not allocate AVFrame", path);
1522 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1525 new_av_frame->width = width;
1526 new_av_frame->height = height;
1527 new_av_frame->format = pix_fmt;
1531 return new_av_frame;
1535 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1538 int source_image_width = frame->GetWidth();
1539 int source_image_height = frame->GetHeight();
1542 if (source_image_height == 1 && source_image_width == 1)
1546 if (image_rescalers.size() == 0)
1547 InitScalers(source_image_width, source_image_height);
1550 SwsContext *scaler = image_rescalers[rescaler_position];
1551 rescaler_position++;
1552 if (rescaler_position == num_of_rescalers)
1553 rescaler_position = 0;
1555 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1558 int bytes_source = 0;
1559 int bytes_final = 0;
1560 AVFrame *frame_source = NULL;
1561 const uchar *pixels = NULL;
1564 pixels = frame->GetPixels();
1567 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1569 AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format),
info.
width,
info.
height, &bytes_final, NULL);
1571 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1576 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1579 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1580 source_image_height, frame_final->data, frame_final->linesize);
1583 #pragma omp critical (av_frames_section) 1584 add_avframe(frame, frame_final);
1594 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1596 #if (LIBAVFORMAT_VERSION_MAJOR >= 58) 1597 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"oc->oformat->flags", oc->oformat->flags,
"", -1,
"", -1,
"", -1,
"", -1);
1599 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE,
"", -1,
"", -1,
"", -1,
"", -1);
1601 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1604 av_init_packet(&pkt);
1606 pkt.flags |= AV_PKT_FLAG_KEY;
1607 pkt.stream_index= video_st->index;
1608 pkt.data= (uint8_t*)frame_final->data;
1609 pkt.size=
sizeof(AVPicture);
1612 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1613 pkt.pts = write_video_count;
1616 int error_code = av_interleaved_write_frame(oc, &pkt);
1619 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1631 av_init_packet(&pkt);
1634 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1637 uint8_t *video_outbuf = NULL;
1640 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1643 frame_final->pts = write_video_count;
1646 int got_packet_ptr = 0;
1650 int frameFinished = 0;
1651 int ret = avcodec_send_frame(video_codec, frame_final);
1654 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet (Frame not sent)",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1655 if (ret == AVERROR(EAGAIN) )
1656 cerr <<
"Frame EAGAIN" <<
"\n";
1657 if (ret == AVERROR_EOF )
1658 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1659 avcodec_send_frame(video_codec, NULL);
1663 ret = avcodec_receive_packet(video_codec, &pkt);
1664 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1665 avcodec_flush_buffers(video_codec);
1676 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1678 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1679 if (error_code != 0 )
1680 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1681 if (got_packet_ptr == 0 )
1682 cerr <<
"Frame gotpacket error" <<
"\n";
1685 int video_outbuf_size = 200000;
1686 video_outbuf = (uint8_t*) av_malloc(200000);
1689 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1693 if(video_codec->coded_frame->key_frame)
1694 pkt.flags |= AV_PKT_FLAG_KEY;
1695 pkt.data= video_outbuf;
1705 if (error_code == 0 && got_packet_ptr) {
1712 if (pkt.pts != AV_NOPTS_VALUE)
1713 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1714 if (pkt.dts != AV_NOPTS_VALUE)
1715 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1716 if (pkt.duration > 0)
1717 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1718 pkt.stream_index = video_st->index;
1721 int error_code = av_interleaved_write_frame(oc, &pkt);
1724 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1731 delete[] video_outbuf;
1745 av_dump_format(oc, 0, path.c_str(), 1);
1749 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1752 for (
int x = 0; x < num_of_rescalers; x++)
1755 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
info.
width,
info.
height,
AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), SWS_LANCZOS, NULL, NULL, NULL);
1758 image_rescalers.push_back(img_convert_ctx);
1764 original_sample_rate = sample_rate;
1765 original_channels = channels;
1772 for (
int x = 0; x < num_of_rescalers; x++)
1773 sws_freeContext(image_rescalers[x]);
1776 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 FF_NUM_PROCESSORS
#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 MY_INPUT_BUFFER_PADDING_SIZE
#define AV_GET_IMAGE_SIZE(pix_fmt, width, height)
#define AV_OUTPUT_CONTEXT(output_context, path)
bool has_video
Determines if this file has a video stream.
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 SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count)
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
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)