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)
45 info.has_audio =
false;
46 info.has_video =
false;
71 void FFmpegWriter::auto_detect_format()
74 fmt = av_guess_format(NULL, path.c_str(), NULL);
76 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
79 oc = avformat_alloc_context();
81 throw OutOfMemory(
"Could not allocate memory for AVFormatContext.", path);
89 info.
vcodec = avcodec_find_encoder(fmt->video_codec)->name;
93 info.
acodec = avcodec_find_encoder(fmt->audio_codec)->name;
97 void FFmpegWriter::initialize_streams()
99 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::initialize_streams",
"fmt->video_codec", fmt->video_codec,
"fmt->audio_codec", fmt->audio_codec,
"AV_CODEC_ID_NONE", AV_CODEC_ID_NONE,
"", -1,
"", -1,
"", -1);
106 video_st = add_video_stream();
110 audio_st = add_audio_stream();
118 if (codec.length() > 0)
120 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
121 if (new_codec == NULL)
122 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
128 fmt->video_codec = new_codec->id;
145 if (pixel_ratio.num > 0)
150 if (bit_rate >= 1000)
166 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);
177 if (codec.length() > 0)
179 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
180 if (new_codec == NULL)
181 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
188 fmt->audio_codec = new_codec->id;
191 if (sample_rate > 7999)
200 if (original_sample_rate == 0)
202 if (original_channels == 0)
205 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetAudioOptions (" + codec +
")",
"sample_rate", sample_rate,
"channels", channels,
"bit_rate", bit_rate,
"", -1,
"", -1,
"", -1);
215 AVCodecContext *c = NULL;
216 stringstream convert(value);
223 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
226 const AVOption *option = NULL;
231 #if LIBAVFORMAT_VERSION_MAJOR <= 53 232 option = av_find_opt(c->priv_data, name.c_str(), NULL, NULL, NULL);
234 option = av_opt_find(c->priv_data, name.c_str(), NULL, 0, 0);
238 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
239 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate"))
244 convert >> c->gop_size;
246 else if (name ==
"qmin")
250 else if (name ==
"qmax")
254 else if (name ==
"max_b_frames")
256 convert >> c->max_b_frames;
258 else if (name ==
"mb_decision")
260 convert >> c->mb_decision;
262 else if (name ==
"level")
266 else if (name ==
"profile")
268 convert >> c->profile;
270 else if (name ==
"slices")
272 convert >> c->slices;
274 else if (name ==
"rc_min_rate")
276 convert >> c->rc_min_rate;
278 else if (name ==
"rc_max_rate")
280 convert >> c->rc_max_rate;
282 else if (name ==
"rc_buffer_size")
284 convert >> c->rc_buffer_size;
288 #if LIBAVFORMAT_VERSION_MAJOR <= 53 289 av_set_string3 (c->priv_data, name.c_str(), value.c_str(), 0, NULL);
291 av_opt_set (c->priv_data, name.c_str(), value.c_str(), 0);
294 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetOption (" + (
string)name +
")",
"stream == VIDEO_STREAM", stream ==
VIDEO_STREAM,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
298 throw InvalidOptions(
"The option is not valid for this codec.", path);
306 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
308 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::PrepareStreams [" + path +
"]",
"info.has_audio",
info.
has_audio,
"info.has_video",
info.
has_video,
"", -1,
"", -1,
"", -1,
"", -1);
311 initialize_streams();
315 open_video(oc, video_st);
317 open_audio(oc, audio_st);
320 prepare_streams =
true;
327 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
330 if (!(fmt->flags & AVFMT_NOFILE)) {
331 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
332 throw InvalidFile(
"Could not open or write file.", path);
336 snprintf(oc->filename,
sizeof(oc->filename),
"%s", path.c_str());
340 avformat_write_header(oc, NULL);
345 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
353 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
358 spooled_video_frames.push_back(frame);
361 spooled_audio_frames.push_back(frame);
363 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);
366 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
371 write_queued_frames();
380 write_queued_frames();
391 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);
397 queued_video_frames = spooled_video_frames;
398 queued_audio_frames = spooled_audio_frames;
401 spooled_video_frames.clear();
402 spooled_audio_frames.clear();
407 omp_set_nested(
true);
410 bool has_error_encoding_video =
false;
417 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
418 write_audio_packets(
false);
421 while (!queued_video_frames.empty())
424 std::shared_ptr<Frame> frame = queued_video_frames.front();
427 processed_frames.push_back(frame);
431 process_video_packet(frame);
434 queued_video_frames.pop_front();
442 while (!processed_frames.empty())
445 std::shared_ptr<Frame> frame = processed_frames.front();
450 deallocate_frames.push_back(frame);
453 if (av_frames.count(frame))
456 AVFrame *frame_final = av_frames[frame];
459 bool success = write_video_packet(frame, frame_final);
461 has_error_encoding_video =
true;
466 processed_frames.pop_front();
470 while (!deallocate_frames.empty())
473 std::shared_ptr<Frame> frame = deallocate_frames.front();
476 if (av_frames.count(frame))
479 AVFrame *av_frame = av_frames[frame];
482 av_freep(&(av_frame->data[0]));
484 av_frames.erase(frame);
488 deallocate_frames.pop_front();
498 if (has_error_encoding_video)
505 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
508 for (
long int number = start; number <= length; number++)
511 std::shared_ptr<Frame> f = reader->GetFrame(number);
522 write_queued_frames();
526 write_audio_packets(
true);
535 av_write_trailer(oc);
538 write_trailer =
true;
540 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
544 void FFmpegWriter::flush_encoders()
546 if (
info.
has_audio && audio_codec && audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_codec->frame_size <= 1)
548 if (
info.
has_video && video_st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && video_codec->codec->id == AV_CODEC_ID_RAWVIDEO)
552 int stop_encoding = 1;
559 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
562 av_init_packet(&pkt);
567 uint8_t *video_outbuf = NULL;
573 #if LIBAVFORMAT_VERSION_MAJOR >= 54 575 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
581 int video_outbuf_size = 0;
584 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
588 if(video_codec->coded_frame->key_frame)
589 pkt.flags |= AV_PKT_FLAG_KEY;
590 pkt.data= video_outbuf;
598 if (error_code < 0) {
599 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
610 if (pkt.pts != AV_NOPTS_VALUE)
611 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
612 if (pkt.dts != AV_NOPTS_VALUE)
613 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
614 if (pkt.duration > 0)
615 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
616 pkt.stream_index = video_st->index;
619 error_code = av_interleaved_write_frame(oc, &pkt);
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);
626 av_freep(&video_outbuf);
634 #if LIBAVFORMAT_VERSION_MAJOR >= 54 636 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);
638 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
642 av_init_packet(&pkt);
645 pkt.pts = pkt.dts = write_audio_count;
649 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
650 if (error_code < 0) {
651 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
660 pkt.pts = pkt.dts = write_audio_count;
663 if (pkt.pts != AV_NOPTS_VALUE)
664 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
665 if (pkt.dts != AV_NOPTS_VALUE)
666 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
667 if (pkt.duration > 0)
668 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
671 pkt.stream_index = audio_st->index;
672 pkt.flags |= AV_PKT_FLAG_KEY;
675 error_code = av_interleaved_write_frame(oc, &pkt);
676 if (error_code < 0) {
677 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
688 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
690 avcodec_close(st->codec);
695 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
697 avcodec_close(st->codec);
702 delete[] audio_outbuf;
703 delete[] audio_encoder_buffer;
706 audio_encoder_buffer = NULL;
710 avresample_close(avr);
711 avresample_free(&avr);
716 avresample_close(avr_planar);
717 avresample_free(&avr_planar);
731 close_video(oc, video_st);
733 close_audio(oc, audio_st);
736 if (image_rescalers.size() > 0)
740 for (
int i = 0; i < oc->nb_streams; i++) {
741 av_freep(&oc->streams[i]->codec);
742 av_freep(&oc->streams[i]);
745 if (!(fmt->flags & AVFMT_NOFILE)) {
751 write_video_count = 0;
752 write_audio_count = 0;
759 prepare_streams =
false;
760 write_header =
false;
761 write_trailer =
false;
763 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
767 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
770 if (!av_frames.count(frame))
773 av_frames[frame] = av_frame;
783 AVStream* FFmpegWriter::add_audio_stream()
789 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
791 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
794 st = avformat_new_stream(oc, codec);
796 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
799 avcodec_get_context_defaults3(st->codec, codec);
802 c->codec_id = codec->id;
803 #if LIBAVFORMAT_VERSION_MAJOR >= 53 804 c->codec_type = AVMEDIA_TYPE_AUDIO;
806 c->codec_type = CODEC_TYPE_AUDIO;
814 if (codec->supported_samplerates) {
816 for (i = 0; codec->supported_samplerates[i] != 0; i++)
823 if (codec->supported_samplerates[i] == 0)
824 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
832 if (codec->channel_layouts) {
834 for (i = 0; codec->channel_layouts[i] != 0; i++)
835 if (channel_layout == codec->channel_layouts[i])
838 c->channel_layout = channel_layout;
841 if (codec->channel_layouts[i] == 0)
842 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
845 c->channel_layout = channel_layout;
848 if (codec->sample_fmts) {
849 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
852 c->sample_fmt = codec->sample_fmts[i];
856 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
858 c->sample_fmt = AV_SAMPLE_FMT_S16;
862 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
863 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
865 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);
871 AVStream* FFmpegWriter::add_video_stream()
877 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
879 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
882 st = avformat_new_stream(oc, codec);
884 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
887 avcodec_get_context_defaults3(st->codec, codec);
890 c->codec_id = codec->id;
891 #if LIBAVFORMAT_VERSION_MAJOR >= 53 892 c->codec_type = AVMEDIA_TYPE_VIDEO;
894 c->codec_type = CODEC_TYPE_VIDEO;
901 c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
917 c->max_b_frames = 10;
918 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
921 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
927 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
928 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
931 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
932 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
935 c->pix_fmt = *supported_pixel_formats;
936 ++supported_pixel_formats;
941 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
945 if (strcmp(fmt->name,
"gif") != 0)
948 oc->oformat->flags |= AVFMT_RAWPICTURE;
955 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);
961 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
964 audio_codec = st->codec;
970 codec = avcodec_find_encoder(audio_codec->codec_id);
975 if (avcodec_open2(audio_codec, codec, NULL) < 0)
980 if (audio_codec->frame_size <= 1) {
984 switch (st->codec->codec_id) {
985 case AV_CODEC_ID_PCM_S16LE:
986 case AV_CODEC_ID_PCM_S16BE:
987 case AV_CODEC_ID_PCM_U16LE:
988 case AV_CODEC_ID_PCM_U16BE:
989 audio_input_frame_size >>= 1;
996 audio_input_frame_size = audio_codec->frame_size;
1000 initial_audio_input_frame_size = audio_input_frame_size;
1007 audio_outbuf =
new uint8_t[audio_outbuf_size];
1011 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1013 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);
1018 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1021 video_codec = st->codec;
1027 codec = avcodec_find_encoder(video_codec->codec_id);
1032 if(video_codec->max_b_frames && video_codec->codec_id != AV_CODEC_ID_MPEG4 && video_codec->codec_id != AV_CODEC_ID_MPEG1VIDEO && video_codec->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1033 video_codec->max_b_frames = 0;
1036 if (avcodec_open2(video_codec, codec, NULL) < 0)
1039 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1044 void FFmpegWriter::write_audio_packets(
bool final)
1046 #pragma omp task firstprivate(final) 1049 int total_frame_samples = 0;
1050 int frame_position = 0;
1051 int channels_in_frame = 0;
1052 int sample_rate_in_frame = 0;
1053 int samples_in_frame = 0;
1058 int16_t* all_resampled_samples = NULL;
1059 int16_t* final_samples_planar = NULL;
1060 int16_t* final_samples = NULL;
1063 while (!queued_audio_frames.empty())
1066 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1069 sample_rate_in_frame = frame->SampleRate();
1070 samples_in_frame = frame->GetAudioSamplesCount();
1071 channels_in_frame = frame->GetAudioChannelsCount();
1072 channel_layout_in_frame = frame->ChannelsLayout();
1076 float* frame_samples_float = NULL;
1078 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1082 total_frame_samples = samples_in_frame * channels_in_frame;
1085 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1087 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1091 delete[] frame_samples_float;
1094 queued_audio_frames.pop_front();
1100 total_frame_samples = frame_position;
1101 int remaining_frame_samples = total_frame_samples;
1102 int samples_position = 0;
1105 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets",
"final",
final,
"total_frame_samples", total_frame_samples,
"channel_layout_in_frame", channel_layout_in_frame,
"channels_in_frame", channels_in_frame,
"samples_in_frame", samples_in_frame,
"LAYOUT_MONO",
LAYOUT_MONO);
1108 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1110 AVFrame *audio_frame = NULL;
1115 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1118 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1119 audio_encoder_buffer_size, 0);
1122 switch (audio_codec->sample_fmt)
1124 case AV_SAMPLE_FMT_FLTP:
1126 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1129 case AV_SAMPLE_FMT_S32P:
1131 output_sample_fmt = AV_SAMPLE_FMT_S32;
1134 case AV_SAMPLE_FMT_S16P:
1136 output_sample_fmt = AV_SAMPLE_FMT_S16;
1139 case AV_SAMPLE_FMT_U8P:
1141 output_sample_fmt = AV_SAMPLE_FMT_U8;
1147 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1148 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1151 remaining_frame_samples = total_frame_samples;
1156 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1157 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1159 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (1st resampling)",
"in_sample_fmt", AV_SAMPLE_FMT_S16,
"out_sample_fmt", output_sample_fmt,
"in_sample_rate", sample_rate_in_frame,
"out_sample_rate",
info.
sample_rate,
"in_channels", channels_in_frame,
"out_channels",
info.
channels);
1163 avr = avresample_alloc_context();
1164 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1166 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1167 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1168 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1170 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1172 avresample_open(avr);
1177 nb_samples = avresample_convert(avr,
1178 audio_converted->data,
1179 audio_converted->linesize[0],
1180 audio_converted->nb_samples,
1182 audio_frame->linesize[0],
1183 audio_frame->nb_samples);
1186 all_resampled_samples = (int16_t*)av_malloc(
sizeof(int16_t) * nb_samples *
info.
channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1189 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1192 av_freep(&(audio_frame->data[0]));
1194 av_freep(&audio_converted->data[0]);
1196 all_queued_samples = NULL;
1198 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
"nb_samples", nb_samples,
"remaining_frame_samples", remaining_frame_samples,
"", -1,
"", -1,
"", -1,
"", -1);
1202 while (remaining_frame_samples > 0 ||
final) {
1204 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1208 if (remaining_frame_samples >= remaining_packet_samples)
1209 diff = remaining_packet_samples;
1210 else if (remaining_frame_samples < remaining_packet_samples)
1211 diff = remaining_frame_samples;
1216 memcpy(samples + (audio_input_position * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))), all_resampled_samples + samples_position, diff * av_get_bytes_per_sample(output_sample_fmt));
1219 audio_input_position += diff;
1220 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1221 remaining_frame_samples -= diff;
1222 remaining_packet_samples -= diff;
1225 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1232 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1234 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
"in_sample_fmt", output_sample_fmt,
"out_sample_fmt", audio_codec->sample_fmt,
"in_sample_rate",
info.
sample_rate,
"out_sample_rate",
info.
sample_rate,
"in_channels",
info.
channels,
"out_channels",
info.
channels);
1238 avr_planar = avresample_alloc_context();
1241 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1242 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1245 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1246 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1247 avresample_open(avr_planar);
1253 audio_frame->nb_samples = audio_input_position /
info.
channels;
1256 final_samples_planar = (int16_t*)av_malloc(
sizeof(int16_t) * audio_frame->nb_samples *
info.
channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1259 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1262 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1263 audio_encoder_buffer_size, 0);
1266 frame_final->nb_samples = audio_input_frame_size;
1267 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1270 int nb_samples = avresample_convert(avr_planar,
1272 frame_final->linesize[0],
1273 frame_final->nb_samples,
1275 audio_frame->linesize[0],
1276 audio_frame->nb_samples);
1280 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1283 av_freep(&(audio_frame->data[0]));
1285 all_queued_samples = NULL;
1287 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1291 final_samples =
new int16_t[audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))];
1294 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1297 frame_final->nb_samples = audio_input_frame_size;
1300 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1301 audio_encoder_buffer_size, 0);
1305 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1306 frame_final->pts = write_audio_count;
1310 av_init_packet(&pkt);
1311 pkt.data = audio_encoder_buffer;
1312 pkt.size = audio_encoder_buffer_size;
1315 pkt.pts = pkt.dts = write_audio_count;
1318 int got_packet_ptr = 0;
1319 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1322 if (error_code == 0 && got_packet_ptr) {
1326 pkt.pts = pkt.dts = write_audio_count;
1329 if (pkt.pts != AV_NOPTS_VALUE)
1330 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1331 if (pkt.dts != AV_NOPTS_VALUE)
1332 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1333 if (pkt.duration > 0)
1334 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1337 pkt.stream_index = audio_st->index;
1338 pkt.flags |= AV_PKT_FLAG_KEY;
1341 int error_code = av_interleaved_write_frame(oc, &pkt);
1344 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1350 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1354 av_freep(&(frame_final->data[0]));
1361 audio_input_position = 0;
1366 if (all_resampled_samples) {
1367 av_freep(&all_resampled_samples);
1368 all_resampled_samples = NULL;
1370 if (all_queued_samples) {
1371 av_freep(&all_queued_samples);
1372 all_queued_samples = NULL;
1379 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1382 AVFrame *new_av_frame = NULL;
1386 if (new_av_frame == NULL)
1387 throw OutOfMemory(
"Could not allocate AVFrame", path);
1390 *buffer_size = avpicture_get_size(pix_fmt, width, height);
1396 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1398 avpicture_fill((AVPicture *)new_av_frame, new_buffer, pix_fmt, width, height);
1399 new_av_frame->width = width;
1400 new_av_frame->height = height;
1401 new_av_frame->format = pix_fmt;
1405 return new_av_frame;
1409 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1412 int source_image_width = frame->GetWidth();
1413 int source_image_height = frame->GetHeight();
1416 if (source_image_height == 1 && source_image_width == 1)
1420 if (image_rescalers.size() == 0)
1421 InitScalers(source_image_width, source_image_height);
1424 SwsContext *scaler = image_rescalers[rescaler_position];
1425 rescaler_position++;
1426 if (rescaler_position == num_of_rescalers)
1427 rescaler_position = 0;
1429 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1432 int bytes_source = 0;
1433 int bytes_final = 0;
1434 AVFrame *frame_source = NULL;
1435 const uchar *pixels = NULL;
1438 pixels = frame->GetPixels();
1441 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1442 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1445 avpicture_fill((AVPicture *) frame_source, (uint8_t*)pixels,
PIX_FMT_RGBA, source_image_width, source_image_height);
1446 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1449 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1450 source_image_height, frame_final->data, frame_final->linesize);
1453 #pragma omp critical (av_frames_section) 1454 add_avframe(frame, frame_final);
1464 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1466 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE,
"", -1,
"", -1,
"", -1,
"", -1);
1468 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1471 av_init_packet(&pkt);
1473 pkt.flags |= AV_PKT_FLAG_KEY;
1474 pkt.stream_index= video_st->index;
1475 pkt.data= (uint8_t*)frame_final->data;
1476 pkt.size=
sizeof(AVPicture);
1479 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1480 pkt.pts = write_video_count;
1483 int error_code = av_interleaved_write_frame(oc, &pkt);
1486 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1496 av_init_packet(&pkt);
1499 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1502 uint8_t *video_outbuf = NULL;
1505 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1508 frame_final->pts = write_video_count;
1511 int got_packet_ptr = 0;
1513 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1515 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1521 int video_outbuf_size = 200000;
1522 video_outbuf = (uint8_t*) av_malloc(200000);
1525 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1529 if(video_codec->coded_frame->key_frame)
1530 pkt.flags |= AV_PKT_FLAG_KEY;
1531 pkt.data= video_outbuf;
1540 if (error_code == 0 && got_packet_ptr) {
1547 if (pkt.pts != AV_NOPTS_VALUE)
1548 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1549 if (pkt.dts != AV_NOPTS_VALUE)
1550 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1551 if (pkt.duration > 0)
1552 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1553 pkt.stream_index = video_st->index;
1556 int error_code = av_interleaved_write_frame(oc, &pkt);
1559 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1566 delete[] video_outbuf;
1580 av_dump_format(oc, 0, path.c_str(), 1);
1584 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1588 c = video_st->codec;
1591 for (
int x = 0; x < num_of_rescalers; x++)
1594 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
info.
width,
info.
height, c->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
1597 image_rescalers.push_back(img_convert_ctx);
1603 original_sample_rate = sample_rate;
1604 original_channels = channels;
1611 for (
int x = 0; x < num_of_rescalers; x++)
1612 sws_freeContext(image_rescalers[x]);
1615 image_rescalers.clear();
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
A video stream (used to determine which type of stream)
#define AV_FREE_FRAME(av_frame)
void SetOption(StreamType stream, string name, string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
int num
Numerator for the fraction.
WriterInfo info
Information about the current media file.
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
An audio stream (used to determine which type of stream)
int video_bit_rate
The bit rate of the video stream (in bytes)
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Exception when an invalid # of audio channels are detected.
string acodec
The name of the audio codec used to encode / decode the video stream.
string vcodec
The name of the video codec used to encode / decode the video stream.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
This abstract class is the base class, used by all readers in libopenshot.
int width
The width of the video (in pixels)
int audio_bit_rate
The bit rate of the audio stream (in bytes)
#define OPEN_MP_NUM_PROCESSORS
void WriteFrame(std::shared_ptr< Frame > frame)
Add a frame to the stack waiting to be encoded.
Exception when encoding audio packet.
Exception when invalid sample rate is detected during encoding.
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
void SetVideoOptions(bool has_video, string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
Exception when invalid encoding options are used.
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Exception for files that can not be found or opened.
FFmpegWriter(string path)
Constructor for FFmpegWriter. Throws one of the following exceptions.
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information.
This class represents a fraction.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
#define av_err2str(errnum)
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
void Close()
Close the writer.
bool interlaced_frame
Are the contents of this frame interlaced.
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
bool has_video
Determines if this file has a video stream.
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
This namespace is the default namespace for all code in the openshot library.
bool has_audio
Determines if this file has an audio stream.
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate)
Set audio export options.
Exception when a writer is closed, and a frame is requested.
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
int height
The height of the video (in pixels)
int den
Denominator for the fraction.
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)