31 #include "../include/FFmpegWriter.h" 36 path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL),
37 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
38 initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32),
39 rescaler_position(0), video_codec(NULL), audio_codec(NULL), is_writing(false), write_video_count(0), write_audio_count(0),
40 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
41 write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL)
71 void FFmpegWriter::auto_detect_format()
74 fmt = av_guess_format(NULL, path.c_str(), NULL);
76 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
79 oc = avformat_alloc_context();
81 throw OutOfMemory(
"Could not allocate memory for AVFormatContext.", path);
89 info.
vcodec = avcodec_find_encoder(fmt->video_codec)->name;
93 info.
acodec = avcodec_find_encoder(fmt->audio_codec)->name;
97 void FFmpegWriter::initialize_streams()
99 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::initialize_streams",
"fmt->video_codec", fmt->video_codec,
"fmt->audio_codec", fmt->audio_codec,
"AV_CODEC_ID_NONE", AV_CODEC_ID_NONE,
"", -1,
"", -1,
"", -1);
106 video_st = add_video_stream();
110 audio_st = add_audio_stream();
117 if (codec.length() > 0)
119 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
120 if (new_codec == NULL)
121 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
127 fmt->video_codec = new_codec->id;
144 if (pixel_ratio.
num > 0)
149 if (bit_rate >= 1000)
165 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetVideoOptions (" + codec +
")",
"width", width,
"height", height,
"size.num", size.
num,
"size.den", size.
den,
"fps.num", fps.
num,
"fps.den", fps.
den);
175 if (codec.length() > 0)
177 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
178 if (new_codec == NULL)
179 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
186 fmt->audio_codec = new_codec->id;
189 if (sample_rate > 7999)
198 if (original_sample_rate == 0)
200 if (original_channels == 0)
203 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetAudioOptions (" + codec +
")",
"sample_rate", sample_rate,
"channels", channels,
"bit_rate", bit_rate,
"", -1,
"", -1,
"", -1);
213 AVCodecContext *c = NULL;
214 stringstream convert(value);
221 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
224 const AVOption *option = NULL;
229 #if LIBAVFORMAT_VERSION_MAJOR <= 53 230 option = av_find_opt(c->priv_data, name.c_str(), NULL, NULL, NULL);
232 option = av_opt_find(c->priv_data, name.c_str(), NULL, 0, 0);
236 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
237 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate"))
242 convert >> c->gop_size;
244 else if (name ==
"qmin")
248 else if (name ==
"qmax")
252 else if (name ==
"max_b_frames")
254 convert >> c->max_b_frames;
256 else if (name ==
"mb_decision")
258 convert >> c->mb_decision;
260 else if (name ==
"level")
264 else if (name ==
"profile")
266 convert >> c->profile;
268 else if (name ==
"slices")
270 convert >> c->slices;
272 else if (name ==
"rc_min_rate")
274 convert >> c->rc_min_rate;
276 else if (name ==
"rc_max_rate")
278 convert >> c->rc_max_rate;
280 else if (name ==
"rc_buffer_size")
282 convert >> c->rc_buffer_size;
286 #if LIBAVFORMAT_VERSION_MAJOR <= 53 287 av_set_string3 (c->priv_data, name.c_str(), value.c_str(), 0, NULL);
289 av_opt_set (c->priv_data, name.c_str(), value.c_str(), 0);
292 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetOption (" + (
string)name +
")",
"stream == VIDEO_STREAM", stream ==
VIDEO_STREAM,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
296 throw InvalidOptions(
"The option is not valid for this codec.", path);
304 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
306 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::PrepareStreams [" + path +
"]",
"info.has_audio",
info.
has_audio,
"info.has_video",
info.
has_video,
"", -1,
"", -1,
"", -1,
"", -1);
309 initialize_streams();
313 open_video(oc, video_st);
315 open_audio(oc, audio_st);
318 prepare_streams =
true;
325 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
328 if (!(fmt->flags & AVFMT_NOFILE)) {
329 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
330 throw InvalidFile(
"Could not open or write file.", path);
334 snprintf(oc->filename,
sizeof(oc->filename),
"%s", path.c_str());
338 avformat_write_header(oc, NULL);
343 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
351 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
356 spooled_video_frames.push_back(frame);
359 spooled_audio_frames.push_back(frame);
361 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame",
"frame->number", frame->number,
"spooled_video_frames.size()", spooled_video_frames.size(),
"spooled_audio_frames.size()", spooled_audio_frames.size(),
"cache_size", cache_size,
"is_writing", is_writing,
"", -1);
364 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
369 write_queued_frames();
378 write_queued_frames();
387 void FFmpegWriter::write_queued_frames()
389 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_queued_frames",
"spooled_video_frames.size()", spooled_video_frames.size(),
"spooled_audio_frames.size()", spooled_audio_frames.size(),
"", -1,
"", -1,
"", -1,
"", -1);
395 queued_video_frames = spooled_video_frames;
396 queued_audio_frames = spooled_audio_frames;
399 spooled_video_frames.clear();
400 spooled_audio_frames.clear();
405 omp_set_nested(
true);
408 bool has_error_encoding_video =
false;
415 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
416 write_audio_packets(
false);
419 while (!queued_video_frames.empty())
422 std::shared_ptr<Frame> frame = queued_video_frames.front();
425 processed_frames.push_back(frame);
429 process_video_packet(frame);
432 queued_video_frames.pop_front();
440 while (!processed_frames.empty())
443 std::shared_ptr<Frame> frame = processed_frames.front();
448 deallocate_frames.push_back(frame);
451 if (av_frames.count(frame))
454 AVFrame *frame_final = av_frames[frame];
457 bool success = write_video_packet(frame, frame_final);
459 has_error_encoding_video =
true;
464 processed_frames.pop_front();
468 while (!deallocate_frames.empty())
471 std::shared_ptr<Frame> frame = deallocate_frames.front();
474 if (av_frames.count(frame))
477 AVFrame *av_frame = av_frames[frame];
480 av_freep(&(av_frame->data[0]));
482 av_frames.erase(frame);
486 deallocate_frames.pop_front();
496 if (has_error_encoding_video)
503 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
506 for (int64_t number = start; number <= length; number++)
509 std::shared_ptr<Frame> f = reader->
GetFrame(number);
520 write_queued_frames();
524 write_audio_packets(
true);
533 av_write_trailer(oc);
536 write_trailer =
true;
538 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
542 void FFmpegWriter::flush_encoders()
544 if (
info.
has_audio && audio_codec && audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_codec->frame_size <= 1)
546 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)
550 int stop_encoding = 1;
557 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
560 av_init_packet(&pkt);
565 uint8_t *video_outbuf = NULL;
571 #if LIBAVFORMAT_VERSION_MAJOR >= 54 573 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
579 int video_outbuf_size = 0;
582 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
586 if(video_codec->coded_frame->key_frame)
587 pkt.flags |= AV_PKT_FLAG_KEY;
588 pkt.data= video_outbuf;
596 if (error_code < 0) {
597 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
608 if (pkt.pts != AV_NOPTS_VALUE)
609 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
610 if (pkt.dts != AV_NOPTS_VALUE)
611 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
612 if (pkt.duration > 0)
613 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
614 pkt.stream_index = video_st->index;
617 error_code = av_interleaved_write_frame(oc, &pkt);
618 if (error_code < 0) {
619 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
624 av_freep(&video_outbuf);
632 #if LIBAVFORMAT_VERSION_MAJOR >= 54 634 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);
636 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
640 av_init_packet(&pkt);
643 pkt.pts = pkt.dts = write_audio_count;
647 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
648 if (error_code < 0) {
649 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
658 pkt.pts = pkt.dts = write_audio_count;
661 if (pkt.pts != AV_NOPTS_VALUE)
662 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
663 if (pkt.dts != AV_NOPTS_VALUE)
664 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
665 if (pkt.duration > 0)
666 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
669 pkt.stream_index = audio_st->index;
670 pkt.flags |= AV_PKT_FLAG_KEY;
673 error_code = av_interleaved_write_frame(oc, &pkt);
674 if (error_code < 0) {
675 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
686 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
688 avcodec_close(st->codec);
693 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
695 avcodec_close(st->codec);
700 delete[] audio_outbuf;
701 delete[] audio_encoder_buffer;
704 audio_encoder_buffer = NULL;
708 avresample_close(avr);
709 avresample_free(&avr);
714 avresample_close(avr_planar);
715 avresample_free(&avr_planar);
729 close_video(oc, video_st);
731 close_audio(oc, audio_st);
734 if (image_rescalers.size() > 0)
738 for (
int i = 0; i < oc->nb_streams; i++) {
739 av_freep(&oc->streams[i]->codec);
740 av_freep(&oc->streams[i]);
743 if (!(fmt->flags & AVFMT_NOFILE)) {
749 write_video_count = 0;
750 write_audio_count = 0;
757 prepare_streams =
false;
758 write_header =
false;
759 write_trailer =
false;
761 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
765 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
768 if (!av_frames.count(frame))
771 av_frames[frame] = av_frame;
781 AVStream* FFmpegWriter::add_audio_stream()
787 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
789 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
792 st = avformat_new_stream(oc, codec);
794 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
797 avcodec_get_context_defaults3(st->codec, codec);
800 c->codec_id = codec->id;
801 #if LIBAVFORMAT_VERSION_MAJOR >= 53 802 c->codec_type = AVMEDIA_TYPE_AUDIO;
804 c->codec_type = CODEC_TYPE_AUDIO;
812 if (codec->supported_samplerates) {
814 for (i = 0; codec->supported_samplerates[i] != 0; i++)
821 if (codec->supported_samplerates[i] == 0)
822 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
830 if (codec->channel_layouts) {
832 for (i = 0; codec->channel_layouts[i] != 0; i++)
833 if (channel_layout == codec->channel_layouts[i])
836 c->channel_layout = channel_layout;
839 if (codec->channel_layouts[i] == 0)
840 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
843 c->channel_layout = channel_layout;
846 if (codec->sample_fmts) {
847 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
850 c->sample_fmt = codec->sample_fmts[i];
854 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
856 c->sample_fmt = AV_SAMPLE_FMT_S16;
860 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
861 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
863 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);
869 AVStream* FFmpegWriter::add_video_stream()
875 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
877 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
880 st = avformat_new_stream(oc, codec);
882 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
885 avcodec_get_context_defaults3(st->codec, codec);
888 c->codec_id = codec->id;
889 #if LIBAVFORMAT_VERSION_MAJOR >= 53 890 c->codec_type = AVMEDIA_TYPE_VIDEO;
892 c->codec_type = CODEC_TYPE_VIDEO;
923 c->max_b_frames = 10;
924 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
927 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
933 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
934 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
937 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
938 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
941 c->pix_fmt = *supported_pixel_formats;
942 ++supported_pixel_formats;
947 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
951 if (strcmp(fmt->name,
"gif") != 0)
954 oc->oformat->flags |= AVFMT_RAWPICTURE;
961 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);
967 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
970 audio_codec = st->codec;
976 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
978 codec = avcodec_find_encoder(audio_codec->codec_id);
983 if (avcodec_open2(audio_codec, codec, NULL) < 0)
988 if (audio_codec->frame_size <= 1) {
992 switch (st->codec->codec_id) {
993 case AV_CODEC_ID_PCM_S16LE:
994 case AV_CODEC_ID_PCM_S16BE:
995 case AV_CODEC_ID_PCM_U16LE:
996 case AV_CODEC_ID_PCM_U16BE:
997 audio_input_frame_size >>= 1;
1004 audio_input_frame_size = audio_codec->frame_size;
1008 initial_audio_input_frame_size = audio_input_frame_size;
1015 audio_outbuf =
new uint8_t[audio_outbuf_size];
1019 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1021 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);
1026 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1029 video_codec = st->codec;
1035 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1037 codec = avcodec_find_encoder(video_codec->codec_id);
1042 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)
1043 video_codec->max_b_frames = 0;
1046 if (avcodec_open2(video_codec, codec, NULL) < 0)
1049 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1054 void FFmpegWriter::write_audio_packets(
bool final)
1056 #pragma omp task firstprivate(final) 1059 int total_frame_samples = 0;
1060 int frame_position = 0;
1061 int channels_in_frame = 0;
1062 int sample_rate_in_frame = 0;
1063 int samples_in_frame = 0;
1068 int16_t* all_resampled_samples = NULL;
1069 int16_t* final_samples_planar = NULL;
1070 int16_t* final_samples = NULL;
1073 while (!queued_audio_frames.empty())
1076 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1079 sample_rate_in_frame = frame->SampleRate();
1080 samples_in_frame = frame->GetAudioSamplesCount();
1081 channels_in_frame = frame->GetAudioChannelsCount();
1082 channel_layout_in_frame = frame->ChannelsLayout();
1086 float* frame_samples_float = NULL;
1088 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1092 total_frame_samples = samples_in_frame * channels_in_frame;
1095 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1097 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1101 delete[] frame_samples_float;
1104 queued_audio_frames.pop_front();
1110 total_frame_samples = frame_position;
1111 int remaining_frame_samples = total_frame_samples;
1112 int samples_position = 0;
1115 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);
1118 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1120 AVFrame *audio_frame = NULL;
1125 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1128 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1129 audio_encoder_buffer_size, 0);
1132 switch (audio_codec->sample_fmt)
1134 case AV_SAMPLE_FMT_FLTP:
1136 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1139 case AV_SAMPLE_FMT_S32P:
1141 output_sample_fmt = AV_SAMPLE_FMT_S32;
1144 case AV_SAMPLE_FMT_S16P:
1146 output_sample_fmt = AV_SAMPLE_FMT_S16;
1149 case AV_SAMPLE_FMT_U8P:
1151 output_sample_fmt = AV_SAMPLE_FMT_U8;
1157 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1158 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1161 remaining_frame_samples = total_frame_samples;
1166 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1167 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1169 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);
1173 avr = avresample_alloc_context();
1174 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1176 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1177 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1178 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1180 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1182 avresample_open(avr);
1187 nb_samples = avresample_convert(avr,
1188 audio_converted->data,
1189 audio_converted->linesize[0],
1190 audio_converted->nb_samples,
1192 audio_frame->linesize[0],
1193 audio_frame->nb_samples);
1196 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)));
1199 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1202 av_freep(&(audio_frame->data[0]));
1204 av_freep(&audio_converted->data[0]);
1206 all_queued_samples = NULL;
1208 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);
1212 while (remaining_frame_samples > 0 ||
final) {
1214 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1218 if (remaining_frame_samples >= remaining_packet_samples)
1219 diff = remaining_packet_samples;
1220 else if (remaining_frame_samples < remaining_packet_samples)
1221 diff = remaining_frame_samples;
1226 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));
1229 audio_input_position += diff;
1230 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1231 remaining_frame_samples -= diff;
1232 remaining_packet_samples -= diff;
1235 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1242 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1244 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);
1248 avr_planar = avresample_alloc_context();
1251 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1252 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1255 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1256 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1257 avresample_open(avr_planar);
1263 audio_frame->nb_samples = audio_input_position /
info.
channels;
1266 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)));
1269 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1272 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1273 audio_encoder_buffer_size, 0);
1276 frame_final->nb_samples = audio_input_frame_size;
1277 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1280 int nb_samples = avresample_convert(avr_planar,
1282 frame_final->linesize[0],
1283 frame_final->nb_samples,
1285 audio_frame->linesize[0],
1286 audio_frame->nb_samples);
1290 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1293 av_freep(&(audio_frame->data[0]));
1295 all_queued_samples = NULL;
1297 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1301 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))];
1304 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1307 frame_final->nb_samples = audio_input_frame_size;
1310 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1311 audio_encoder_buffer_size, 0);
1315 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1316 frame_final->pts = write_audio_count;
1320 av_init_packet(&pkt);
1321 pkt.data = audio_encoder_buffer;
1322 pkt.size = audio_encoder_buffer_size;
1325 pkt.pts = pkt.dts = write_audio_count;
1328 int got_packet_ptr = 0;
1329 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1332 if (error_code == 0 && got_packet_ptr) {
1336 pkt.pts = pkt.dts = write_audio_count;
1339 if (pkt.pts != AV_NOPTS_VALUE)
1340 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1341 if (pkt.dts != AV_NOPTS_VALUE)
1342 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1343 if (pkt.duration > 0)
1344 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1347 pkt.stream_index = audio_st->index;
1348 pkt.flags |= AV_PKT_FLAG_KEY;
1351 int error_code = av_interleaved_write_frame(oc, &pkt);
1354 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1360 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1364 av_freep(&(frame_final->data[0]));
1371 audio_input_position = 0;
1376 if (all_resampled_samples) {
1377 av_freep(&all_resampled_samples);
1378 all_resampled_samples = NULL;
1380 if (all_queued_samples) {
1381 av_freep(&all_queued_samples);
1382 all_queued_samples = NULL;
1389 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1392 AVFrame *new_av_frame = NULL;
1396 if (new_av_frame == NULL)
1397 throw OutOfMemory(
"Could not allocate AVFrame", path);
1400 *buffer_size = avpicture_get_size(pix_fmt, width, height);
1406 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1408 avpicture_fill((AVPicture *)new_av_frame, new_buffer, pix_fmt, width, height);
1409 new_av_frame->width = width;
1410 new_av_frame->height = height;
1411 new_av_frame->format = pix_fmt;
1415 return new_av_frame;
1419 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1422 int source_image_width = frame->GetWidth();
1423 int source_image_height = frame->GetHeight();
1426 if (source_image_height == 1 && source_image_width == 1)
1430 if (image_rescalers.size() == 0)
1431 InitScalers(source_image_width, source_image_height);
1434 SwsContext *scaler = image_rescalers[rescaler_position];
1435 rescaler_position++;
1436 if (rescaler_position == num_of_rescalers)
1437 rescaler_position = 0;
1439 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1442 int bytes_source = 0;
1443 int bytes_final = 0;
1444 AVFrame *frame_source = NULL;
1445 const uchar *pixels = NULL;
1448 pixels = frame->GetPixels();
1451 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1452 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1455 avpicture_fill((AVPicture *) frame_source, (uint8_t*)pixels,
PIX_FMT_RGBA, source_image_width, source_image_height);
1456 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1459 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1460 source_image_height, frame_final->data, frame_final->linesize);
1463 #pragma omp critical (av_frames_section) 1464 add_avframe(frame, frame_final);
1474 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1476 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);
1478 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1481 av_init_packet(&pkt);
1483 pkt.flags |= AV_PKT_FLAG_KEY;
1484 pkt.stream_index= video_st->index;
1485 pkt.data= (uint8_t*)frame_final->data;
1486 pkt.size=
sizeof(AVPicture);
1489 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1490 pkt.pts = write_video_count;
1493 int error_code = av_interleaved_write_frame(oc, &pkt);
1496 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1506 av_init_packet(&pkt);
1509 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1512 uint8_t *video_outbuf = NULL;
1515 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1518 frame_final->pts = write_video_count;
1521 int got_packet_ptr = 0;
1523 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1525 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1531 int video_outbuf_size = 200000;
1532 video_outbuf = (uint8_t*) av_malloc(200000);
1535 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1539 if(video_codec->coded_frame->key_frame)
1540 pkt.flags |= AV_PKT_FLAG_KEY;
1541 pkt.data= video_outbuf;
1550 if (error_code == 0 && got_packet_ptr) {
1557 if (pkt.pts != AV_NOPTS_VALUE)
1558 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1559 if (pkt.dts != AV_NOPTS_VALUE)
1560 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1561 if (pkt.duration > 0)
1562 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1563 pkt.stream_index = video_st->index;
1566 int error_code = av_interleaved_write_frame(oc, &pkt);
1569 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1576 delete[] video_outbuf;
1590 av_dump_format(oc, 0, path.c_str(), 1);
1594 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1598 c = video_st->codec;
1601 for (
int x = 0; x < num_of_rescalers; x++)
1607 image_rescalers.push_back(img_convert_ctx);
1613 original_sample_rate = sample_rate;
1614 original_channels = channels;
1621 for (
int x = 0; x < num_of_rescalers; x++)
1622 sws_freeContext(image_rescalers[x]);
1625 image_rescalers.clear();
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
A video stream (used to determine which type of stream)
#define AV_FREE_FRAME(av_frame)
void SetOption(StreamType stream, string name, string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
int num
Numerator for the fraction.
WriterInfo info
Information about the current media file.
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
An audio stream (used to determine which type of stream)
int video_bit_rate
The bit rate of the video stream (in bytes)
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Exception when an invalid # of audio channels are detected.
string acodec
The name of the audio codec used to encode / decode the video stream.
string vcodec
The name of the video codec used to encode / decode the video stream.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
This abstract class is the base class, used by all readers in libopenshot.
int width
The width of the video (in pixels)
int audio_bit_rate
The bit rate of the audio stream (in bytes)
#define OPEN_MP_NUM_PROCESSORS
void WriteFrame(std::shared_ptr< Frame > frame)
Add a frame to the stack waiting to be encoded.
Exception when encoding audio packet.
Exception when invalid sample rate is detected during encoding.
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
void SetVideoOptions(bool has_video, string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
virtual std::shared_ptr< Frame > GetFrame(int64_t number)=0
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
Exception when invalid encoding options are used.
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Exception for files that can not be found or opened.
FFmpegWriter(string path)
Constructor for FFmpegWriter. Throws one of the following exceptions.
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information.
This class represents a fraction.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
#define av_err2str(errnum)
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
void Close()
Close the writer.
bool interlaced_frame
Are the contents of this frame interlaced.
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
bool has_video
Determines if this file has a video stream.
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
This namespace is the default namespace for all code in the openshot library.
bool has_audio
Determines if this file has an audio stream.
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate)
Set audio export options.
Exception when a writer is closed, and a frame is requested.
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
int height
The height of the video (in pixels)
int den
Denominator for the fraction.
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)