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 audio 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);
337 avformat_write_header(oc, NULL);
342 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
350 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
355 spooled_video_frames.push_back(frame);
358 spooled_audio_frames.push_back(frame);
360 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);
363 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
368 write_queued_frames();
377 write_queued_frames();
388 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);
394 queued_video_frames = spooled_video_frames;
395 queued_audio_frames = spooled_audio_frames;
398 spooled_video_frames.clear();
399 spooled_audio_frames.clear();
404 omp_set_nested(
true);
407 bool has_error_encoding_video =
false;
414 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
415 write_audio_packets(
false);
418 while (!queued_video_frames.empty())
421 tr1::shared_ptr<Frame> frame = queued_video_frames.front();
424 processed_frames.push_back(frame);
428 process_video_packet(frame);
431 queued_video_frames.pop_front();
439 while (!processed_frames.empty())
442 tr1::shared_ptr<Frame> frame = processed_frames.front();
447 deallocate_frames.push_back(frame);
450 if (av_frames.count(frame))
453 AVFrame *frame_final = av_frames[frame];
456 bool success = write_video_packet(frame, frame_final);
458 has_error_encoding_video =
true;
463 processed_frames.pop_front();
467 while (!deallocate_frames.empty())
470 tr1::shared_ptr<Frame> frame = deallocate_frames.front();
473 if (av_frames.count(frame))
476 AVFrame *av_frame = av_frames[frame];
479 av_freep(&(av_frame->data[0]));
481 av_frames.erase(frame);
485 deallocate_frames.pop_front();
495 if (has_error_encoding_video)
502 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
505 for (
long int number = start; number <= length; number++)
508 tr1::shared_ptr<Frame> f = reader->GetFrame(number);
519 write_queued_frames();
523 write_audio_packets(
true);
532 av_write_trailer(oc);
535 write_trailer =
true;
537 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
541 void FFmpegWriter::flush_encoders()
543 if (
info.
has_audio && audio_codec && audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_codec->frame_size <= 1)
545 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)
549 int stop_encoding = 1;
556 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
559 av_init_packet(&pkt);
564 uint8_t *video_outbuf = NULL;
570 #if LIBAVFORMAT_VERSION_MAJOR >= 54 572 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
578 int video_outbuf_size = 0;
581 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
585 if(video_codec->coded_frame->key_frame)
586 pkt.flags |= AV_PKT_FLAG_KEY;
587 pkt.data= video_outbuf;
595 if (error_code < 0) {
596 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
607 if (pkt.pts != AV_NOPTS_VALUE)
608 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
609 if (pkt.dts != AV_NOPTS_VALUE)
610 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
611 if (pkt.duration > 0)
612 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
613 pkt.stream_index = video_st->index;
616 error_code = av_interleaved_write_frame(oc, &pkt);
617 if (error_code < 0) {
618 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
623 av_freep(&video_outbuf);
631 #if LIBAVFORMAT_VERSION_MAJOR >= 54 633 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);
635 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base);
639 av_init_packet(&pkt);
642 pkt.pts = pkt.dts = write_audio_count;
646 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
647 if (error_code < 0) {
648 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
657 pkt.pts = pkt.dts = write_audio_count;
660 if (pkt.pts != AV_NOPTS_VALUE)
661 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
662 if (pkt.dts != AV_NOPTS_VALUE)
663 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
664 if (pkt.duration > 0)
665 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
668 pkt.stream_index = audio_st->index;
669 pkt.flags |= AV_PKT_FLAG_KEY;
672 error_code = av_interleaved_write_frame(oc, &pkt);
673 if (error_code < 0) {
674 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
678 av_free_packet(&pkt);
685 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
687 avcodec_close(st->codec);
692 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
694 avcodec_close(st->codec);
699 delete[] audio_outbuf;
700 delete[] audio_encoder_buffer;
703 audio_encoder_buffer = NULL;
707 avresample_close(avr);
708 avresample_free(&avr);
713 avresample_close(avr_planar);
714 avresample_free(&avr_planar);
728 close_video(oc, video_st);
730 close_audio(oc, audio_st);
733 if (image_rescalers.size() > 0)
737 for (
int i = 0; i < oc->nb_streams; i++) {
738 av_freep(&oc->streams[i]->codec);
739 av_freep(&oc->streams[i]);
742 if (!(fmt->flags & AVFMT_NOFILE)) {
748 write_video_count = 0;
749 write_audio_count = 0;
756 prepare_streams =
false;
757 write_header =
false;
758 write_trailer =
false;
760 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
764 void FFmpegWriter::add_avframe(tr1::shared_ptr<Frame> frame, AVFrame* av_frame)
767 if (!av_frames.count(frame))
770 av_frames[frame] = av_frame;
780 AVStream* FFmpegWriter::add_audio_stream()
786 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
788 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
791 st = avformat_new_stream(oc, codec);
793 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
796 avcodec_get_context_defaults3(st->codec, codec);
799 c->codec_id = codec->id;
800 #if LIBAVFORMAT_VERSION_MAJOR >= 53 801 c->codec_type = AVMEDIA_TYPE_AUDIO;
803 c->codec_type = CODEC_TYPE_AUDIO;
811 if (codec->supported_samplerates) {
813 for (i = 0; codec->supported_samplerates[i] != 0; i++)
820 if (codec->supported_samplerates[i] == 0)
821 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
829 if (codec->channel_layouts) {
831 for (i = 0; codec->channel_layouts[i] != 0; i++)
832 if (channel_layout == codec->channel_layouts[i])
835 c->channel_layout = channel_layout;
838 if (codec->channel_layouts[i] == 0)
839 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
842 c->channel_layout = channel_layout;
845 if (codec->sample_fmts) {
846 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
849 c->sample_fmt = codec->sample_fmts[i];
853 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
855 c->sample_fmt = AV_SAMPLE_FMT_S16;
859 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
860 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
862 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);
868 AVStream* FFmpegWriter::add_video_stream()
874 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
876 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
879 st = avformat_new_stream(oc, codec);
881 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
884 avcodec_get_context_defaults3(st->codec, codec);
887 c->codec_id = codec->id;
888 #if LIBAVFORMAT_VERSION_MAJOR >= 53 889 c->codec_type = AVMEDIA_TYPE_VIDEO;
891 c->codec_type = CODEC_TYPE_VIDEO;
898 c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
914 c->max_b_frames = 10;
915 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
918 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
924 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
925 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
928 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
929 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
932 c->pix_fmt = *supported_pixel_formats;
933 ++supported_pixel_formats;
938 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
942 if (strcmp(fmt->name,
"gif") != 0)
945 oc->oformat->flags |= AVFMT_RAWPICTURE;
952 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);
958 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
961 audio_codec = st->codec;
967 codec = avcodec_find_encoder(audio_codec->codec_id);
972 if (avcodec_open2(audio_codec, codec, NULL) < 0)
977 if (audio_codec->frame_size <= 1) {
981 switch (st->codec->codec_id) {
982 case AV_CODEC_ID_PCM_S16LE:
983 case AV_CODEC_ID_PCM_S16BE:
984 case AV_CODEC_ID_PCM_U16LE:
985 case AV_CODEC_ID_PCM_U16BE:
986 audio_input_frame_size >>= 1;
993 audio_input_frame_size = audio_codec->frame_size;
997 initial_audio_input_frame_size = audio_input_frame_size;
1004 audio_outbuf =
new uint8_t[audio_outbuf_size];
1008 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1010 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);
1015 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1018 video_codec = st->codec;
1024 codec = avcodec_find_encoder(video_codec->codec_id);
1029 if (avcodec_open2(video_codec, codec, NULL) < 0)
1032 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1037 void FFmpegWriter::write_audio_packets(
bool final)
1039 #pragma omp task firstprivate(final) 1042 int total_frame_samples = 0;
1043 int frame_position = 0;
1044 int channels_in_frame = 0;
1045 int sample_rate_in_frame = 0;
1046 int samples_in_frame = 0;
1051 int16_t* all_resampled_samples = NULL;
1052 int16_t* final_samples_planar = NULL;
1053 int16_t* final_samples = NULL;
1056 while (!queued_audio_frames.empty())
1059 tr1::shared_ptr<Frame> frame = queued_audio_frames.front();
1062 sample_rate_in_frame = frame->SampleRate();
1063 samples_in_frame = frame->GetAudioSamplesCount();
1064 channels_in_frame = frame->GetAudioChannelsCount();
1065 channel_layout_in_frame = frame->ChannelsLayout();
1069 float* frame_samples_float = NULL;
1071 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1075 total_frame_samples = samples_in_frame * channels_in_frame;
1078 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1080 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1084 delete[] frame_samples_float;
1087 queued_audio_frames.pop_front();
1093 total_frame_samples = frame_position;
1094 int remaining_frame_samples = total_frame_samples;
1095 int samples_position = 0;
1098 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);
1101 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1103 AVFrame *audio_frame = NULL;
1108 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1111 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1112 audio_encoder_buffer_size, 0);
1115 switch (audio_codec->sample_fmt)
1117 case AV_SAMPLE_FMT_FLTP:
1119 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1122 case AV_SAMPLE_FMT_S32P:
1124 output_sample_fmt = AV_SAMPLE_FMT_S32;
1127 case AV_SAMPLE_FMT_S16P:
1129 output_sample_fmt = AV_SAMPLE_FMT_S16;
1132 case AV_SAMPLE_FMT_U8P:
1134 output_sample_fmt = AV_SAMPLE_FMT_U8;
1140 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1141 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1144 remaining_frame_samples = total_frame_samples;
1149 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1150 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1152 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);
1156 avr = avresample_alloc_context();
1157 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1159 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1160 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1161 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1163 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1165 avresample_open(avr);
1170 nb_samples = avresample_convert(avr,
1171 audio_converted->data,
1172 audio_converted->linesize[0],
1173 audio_converted->nb_samples,
1175 audio_frame->linesize[0],
1176 audio_frame->nb_samples);
1179 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)));
1182 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1185 av_freep(&(audio_frame->data[0]));
1187 av_freep(&audio_converted->data[0]);
1189 all_queued_samples = NULL;
1191 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);
1195 while (remaining_frame_samples > 0 ||
final) {
1197 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1201 if (remaining_frame_samples >= remaining_packet_samples)
1202 diff = remaining_packet_samples;
1203 else if (remaining_frame_samples < remaining_packet_samples)
1204 diff = remaining_frame_samples;
1209 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));
1212 audio_input_position += diff;
1213 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1214 remaining_frame_samples -= diff;
1215 remaining_packet_samples -= diff;
1218 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1225 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1227 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);
1231 avr_planar = avresample_alloc_context();
1234 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1235 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1238 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1239 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1240 avresample_open(avr_planar);
1246 audio_frame->nb_samples = audio_input_position /
info.
channels;
1249 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)));
1252 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1255 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1256 audio_encoder_buffer_size, 0);
1259 frame_final->nb_samples = audio_input_frame_size;
1260 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1263 int nb_samples = avresample_convert(avr_planar,
1265 frame_final->linesize[0],
1266 frame_final->nb_samples,
1268 audio_frame->linesize[0],
1269 audio_frame->nb_samples);
1273 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1276 av_freep(&(audio_frame->data[0]));
1278 all_queued_samples = NULL;
1280 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1284 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))];
1287 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1290 frame_final->nb_samples = audio_input_frame_size;
1293 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1294 audio_encoder_buffer_size, 0);
1298 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1299 frame_final->pts = write_audio_count;
1303 av_init_packet(&pkt);
1304 pkt.data = audio_encoder_buffer;
1305 pkt.size = audio_encoder_buffer_size;
1308 pkt.pts = pkt.dts = write_audio_count;
1311 int got_packet_ptr = 0;
1312 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1315 if (error_code == 0 && got_packet_ptr) {
1319 pkt.pts = pkt.dts = write_audio_count;
1322 if (pkt.pts != AV_NOPTS_VALUE)
1323 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1324 if (pkt.dts != AV_NOPTS_VALUE)
1325 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1326 if (pkt.duration > 0)
1327 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1330 pkt.stream_index = audio_st->index;
1331 pkt.flags |= AV_PKT_FLAG_KEY;
1334 int error_code = av_interleaved_write_frame(oc, &pkt);
1337 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1343 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1347 av_freep(&(frame_final->data[0]));
1351 av_free_packet(&pkt);
1354 audio_input_position = 0;
1359 if (all_resampled_samples) {
1360 av_freep(&all_resampled_samples);
1361 all_resampled_samples = NULL;
1363 if (all_queued_samples) {
1364 av_freep(&all_queued_samples);
1365 all_queued_samples = NULL;
1372 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1375 AVFrame *new_av_frame = NULL;
1379 if (new_av_frame == NULL)
1380 throw OutOfMemory(
"Could not allocate AVFrame", path);
1383 *buffer_size = avpicture_get_size(pix_fmt, width, height);
1389 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1391 avpicture_fill((AVPicture *)new_av_frame, new_buffer, pix_fmt, width, height);
1392 new_av_frame->width = width;
1393 new_av_frame->height = height;
1394 new_av_frame->format = pix_fmt;
1398 return new_av_frame;
1402 void FFmpegWriter::process_video_packet(tr1::shared_ptr<Frame> frame)
1405 int source_image_width = frame->GetWidth();
1406 int source_image_height = frame->GetHeight();
1409 if (source_image_height == 1 && source_image_width == 1)
1413 if (image_rescalers.size() == 0)
1414 InitScalers(source_image_width, source_image_height);
1417 SwsContext *scaler = image_rescalers[rescaler_position];
1418 rescaler_position++;
1419 if (rescaler_position == num_of_rescalers)
1420 rescaler_position = 0;
1422 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height) 1425 int bytes_source = 0;
1426 int bytes_final = 0;
1427 AVFrame *frame_source = NULL;
1428 const uchar *pixels = NULL;
1431 pixels = frame->GetPixels();
1434 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1435 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1438 avpicture_fill((AVPicture *) frame_source, (uint8_t*)pixels,
PIX_FMT_RGBA, source_image_width, source_image_height);
1439 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1442 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1443 source_image_height, frame_final->data, frame_final->linesize);
1446 #pragma omp critical (av_frames_section) 1447 add_avframe(frame, frame_final);
1457 bool FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* frame_final)
1459 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);
1461 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1464 av_init_packet(&pkt);
1466 pkt.flags |= AV_PKT_FLAG_KEY;
1467 pkt.stream_index= video_st->index;
1468 pkt.data= (uint8_t*)frame_final->data;
1469 pkt.size=
sizeof(AVPicture);
1472 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1473 pkt.pts = write_video_count;
1476 int error_code = av_interleaved_write_frame(oc, &pkt);
1479 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1484 av_free_packet(&pkt);
1489 av_init_packet(&pkt);
1492 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1495 uint8_t *video_outbuf = NULL;
1498 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1501 frame_final->pts = write_video_count;
1504 int got_packet_ptr = 0;
1506 #if LIBAVFORMAT_VERSION_MAJOR >= 54 1508 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1514 int video_outbuf_size = 200000;
1515 video_outbuf = (uint8_t*) av_malloc(200000);
1518 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1522 if(video_codec->coded_frame->key_frame)
1523 pkt.flags |= AV_PKT_FLAG_KEY;
1524 pkt.data= video_outbuf;
1533 if (error_code == 0 && got_packet_ptr) {
1540 if (pkt.pts != AV_NOPTS_VALUE)
1541 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1542 if (pkt.dts != AV_NOPTS_VALUE)
1543 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1544 if (pkt.duration > 0)
1545 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1546 pkt.stream_index = video_st->index;
1549 int error_code = av_interleaved_write_frame(oc, &pkt);
1552 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1559 delete[] video_outbuf;
1562 av_free_packet(&pkt);
1573 av_dump_format(oc, 0, path.c_str(), 1);
1577 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1581 c = video_st->codec;
1584 for (
int x = 0; x < num_of_rescalers; x++)
1587 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);
1590 image_rescalers.push_back(img_convert_ctx);
1596 original_sample_rate = sample_rate;
1597 original_channels = channels;
1604 for (
int x = 0; x < num_of_rescalers; x++)
1605 sws_freeContext(image_rescalers[x]);
1608 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
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.
void WriteFrame(tr1::shared_ptr< Frame > frame)
Add a frame to the stack waiting to be encoded.
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
Exception when invalid encoding options are used.
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)