31 #include "../include/FFmpegWriter.h"
33 using namespace openshot;
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)
68 open_video(oc, video_st);
70 open_audio(oc, audio_st);
79 void FFmpegWriter::auto_detect_format()
82 fmt = av_guess_format(NULL, path.c_str(), NULL);
84 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
89 throw OutOfMemory(
"Could not allocate memory for AVFormatContext.", path);
97 info.
vcodec = avcodec_find_encoder(fmt->video_codec)->name;
101 info.
acodec = avcodec_find_encoder(fmt->audio_codec)->name;
105 void FFmpegWriter::initialize_streams()
107 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);
114 video_st = add_video_stream();
118 audio_st = add_audio_stream();
125 if (codec.length() > 0)
127 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
128 if (new_codec == NULL)
129 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
135 fmt->video_codec = new_codec->id;
152 if (pixel_ratio.
num > 0)
157 if (bit_rate >= 1000)
159 if ((bit_rate >= 0) && (bit_rate < 64) )
175 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);
185 if (codec.length() > 0)
187 AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
188 if (new_codec == NULL)
189 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
196 fmt->audio_codec = new_codec->id;
199 if (sample_rate > 7999)
208 if (original_sample_rate == 0)
210 if (original_channels == 0)
213 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetAudioOptions (" + codec +
")",
"sample_rate", sample_rate,
"channels", channels,
"bit_rate", bit_rate,
"", -1,
"", -1,
"", -1);
223 AVCodecContext *c = NULL;
225 stringstream convert(value);
238 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
241 const AVOption *option = NULL;
249 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
250 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
256 convert >> c->gop_size;
258 else if (name ==
"qmin")
262 else if (name ==
"qmax")
266 else if (name ==
"max_b_frames")
268 convert >> c->max_b_frames;
270 else if (name ==
"mb_decision")
272 convert >> c->mb_decision;
274 else if (name ==
"level")
278 else if (name ==
"profile")
280 convert >> c->profile;
282 else if (name ==
"slices")
284 convert >> c->slices;
286 else if (name ==
"rc_min_rate")
288 convert >> c->rc_min_rate;
290 else if (name ==
"rc_max_rate")
292 convert >> c->rc_max_rate;
294 else if (name ==
"rc_buffer_size")
296 convert >> c->rc_buffer_size;
298 else if (name ==
"crf") {
302 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101)
303 switch (c->codec_id) {
304 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
305 case AV_CODEC_ID_AV1 :
307 av_opt_set_int(c->priv_data,
"crf", min(stoi(value),63), 0);
310 case AV_CODEC_ID_VP8 :
311 c->bit_rate = 10000000;
312 av_opt_set_int(c->priv_data,
"crf", max(min(stoi(value),63),4), 0);
314 case AV_CODEC_ID_VP9 :
316 av_opt_set_int(c->priv_data,
"crf", min(stoi(value),63), 0);
317 if (stoi(value) == 0) {
318 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
319 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
322 case AV_CODEC_ID_H264 :
323 av_opt_set_int(c->priv_data,
"crf", min(stoi(value),51), 0);
324 if (stoi(value) == 0) {
325 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
328 case AV_CODEC_ID_H265 :
329 av_opt_set_int(c->priv_data,
"crf", min(stoi(value),51), 0);
330 if (stoi(value) == 0) {
331 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
332 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
338 double mbs = 15000000.0;
347 c->bit_rate = (int)(mbs);
354 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
356 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetOption (" + (
string)name +
")",
"stream == VIDEO_STREAM", stream ==
VIDEO_STREAM,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
360 throw InvalidOptions(
"The option is not valid for this codec.", path);
370 if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
380 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
382 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::PrepareStreams [" + path +
"]",
"info.has_audio",
info.
has_audio,
"info.has_video",
info.
has_video,
"", -1,
"", -1,
"", -1,
"", -1);
385 initialize_streams();
388 prepare_streams =
true;
395 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
398 if (!(fmt->flags & AVFMT_NOFILE)) {
399 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
400 throw InvalidFile(
"Could not open or write file.", path);
404 snprintf(oc->AV_FILENAME,
sizeof(oc->AV_FILENAME),
"%s", path.c_str());
412 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
415 if (avformat_write_header(oc, NULL) != 0) {
416 throw InvalidFile(
"Could not write header to file.", path);
422 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteHeader",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
430 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
435 spooled_video_frames.push_back(frame);
438 spooled_audio_frames.push_back(frame);
440 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);
443 if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size)
448 write_queued_frames();
453 write_queued_frames();
462 void FFmpegWriter::write_queued_frames()
464 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);
470 queued_video_frames = spooled_video_frames;
471 queued_audio_frames = spooled_audio_frames;
474 spooled_video_frames.clear();
475 spooled_audio_frames.clear();
480 omp_set_nested(
true);
483 bool has_error_encoding_video =
false;
490 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
491 write_audio_packets(
false);
494 while (!queued_video_frames.empty())
497 std::shared_ptr<Frame> frame = queued_video_frames.front();
500 processed_frames.push_back(frame);
504 process_video_packet(frame);
507 queued_video_frames.pop_front();
515 while (!processed_frames.empty())
518 std::shared_ptr<Frame> frame = processed_frames.front();
523 deallocate_frames.push_back(frame);
526 if (av_frames.count(frame))
529 AVFrame *frame_final = av_frames[frame];
532 bool success = write_video_packet(frame, frame_final);
534 has_error_encoding_video =
true;
539 processed_frames.pop_front();
543 while (!deallocate_frames.empty())
546 std::shared_ptr<Frame> frame = deallocate_frames.front();
549 if (av_frames.count(frame))
552 AVFrame *av_frame = av_frames[frame];
555 av_freep(&(av_frame->data[0]));
557 av_frames.erase(frame);
561 deallocate_frames.pop_front();
571 if (has_error_encoding_video)
578 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame (from Reader)",
"start", start,
"length", length,
"", -1,
"", -1,
"", -1,
"", -1);
581 for (int64_t number = start; number <= length; number++)
584 std::shared_ptr<Frame> f = reader->
GetFrame(number);
595 write_queued_frames();
599 write_audio_packets(
true);
608 av_write_trailer(oc);
611 write_trailer =
true;
613 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteTrailer",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
617 void FFmpegWriter::flush_encoders()
621 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
627 int stop_encoding = 1;
634 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
637 av_init_packet(&pkt);
642 uint8_t *video_outbuf = NULL;
649 #pragma omp critical (write_video_packet)
652 error_code = avcodec_send_frame(video_codec, NULL);
654 while (error_code >= 0) {
655 error_code = avcodec_receive_packet(video_codec, &pkt);
656 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
659 avcodec_flush_buffers(video_codec);
662 if (pkt.pts != AV_NOPTS_VALUE)
663 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
664 if (pkt.dts != AV_NOPTS_VALUE)
665 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
666 if (pkt.duration > 0)
667 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
668 pkt.stream_index = video_st->index;
669 error_code = av_interleaved_write_frame(oc, &pkt);
674 #if LIBAVFORMAT_VERSION_MAJOR >= 54
676 error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
680 int video_outbuf_size = 0;
683 int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
687 if(video_codec->coded_frame->key_frame)
688 pkt.flags |= AV_PKT_FLAG_KEY;
689 pkt.data= video_outbuf;
698 if (error_code < 0) {
699 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
710 if (pkt.pts != AV_NOPTS_VALUE)
711 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
712 if (pkt.dts != AV_NOPTS_VALUE)
713 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
714 if (pkt.duration > 0)
715 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
716 pkt.stream_index = video_st->index;
719 error_code = av_interleaved_write_frame(oc, &pkt);
720 if (error_code < 0) {
721 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
726 av_freep(&video_outbuf);
734 #if LIBAVFORMAT_VERSION_MAJOR >= 54
736 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);
738 write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1,
info.
sample_rate}, audio_codec->time_base);
742 av_init_packet(&pkt);
745 pkt.pts = pkt.dts = write_audio_count;
750 avcodec_send_frame(audio_codec, NULL);
753 error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
755 if (error_code < 0) {
756 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
765 pkt.pts = pkt.dts = write_audio_count;
768 if (pkt.pts != AV_NOPTS_VALUE)
769 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
770 if (pkt.dts != AV_NOPTS_VALUE)
771 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
772 if (pkt.duration > 0)
773 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
776 pkt.stream_index = audio_st->index;
777 pkt.flags |= AV_PKT_FLAG_KEY;
780 error_code = av_interleaved_write_frame(oc, &pkt);
781 if (error_code < 0) {
782 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
793 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
800 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
807 delete[] audio_outbuf;
808 delete[] audio_encoder_buffer;
811 audio_encoder_buffer = NULL;
836 close_video(oc, video_st);
838 close_audio(oc, audio_st);
841 if (image_rescalers.size() > 0)
845 for (
int i = 0; i < oc->nb_streams; i++) {
847 av_freep(&oc->streams[i]);
850 if (!(fmt->flags & AVFMT_NOFILE)) {
856 write_video_count = 0;
857 write_audio_count = 0;
864 prepare_streams =
false;
865 write_header =
false;
866 write_trailer =
false;
868 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::Close",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
872 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame* av_frame)
875 if (!av_frames.count(frame))
878 av_frames[frame] = av_frame;
888 AVStream* FFmpegWriter::add_audio_stream()
894 AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
896 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
901 c->codec_id = codec->
id;
902 #if LIBAVFORMAT_VERSION_MAJOR >= 53
903 c->codec_type = AVMEDIA_TYPE_AUDIO;
905 c->codec_type = CODEC_TYPE_AUDIO;
913 if (codec->supported_samplerates) {
915 for (i = 0; codec->supported_samplerates[i] != 0; i++)
922 if (codec->supported_samplerates[i] == 0)
923 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
931 if (codec->channel_layouts) {
933 for (i = 0; codec->channel_layouts[i] != 0; i++)
934 if (channel_layout == codec->channel_layouts[i])
937 c->channel_layout = channel_layout;
940 if (codec->channel_layouts[i] == 0)
941 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
944 c->channel_layout = channel_layout;
947 if (codec->sample_fmts) {
948 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
951 c->sample_fmt = codec->sample_fmts[i];
955 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
957 c->sample_fmt = AV_SAMPLE_FMT_S16;
961 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
962 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
963 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
965 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
969 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);
975 AVStream* FFmpegWriter::add_video_stream()
981 AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
983 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
988 c->codec_id = codec->
id;
989 #if LIBAVFORMAT_VERSION_MAJOR >= 53
990 c->codec_type = AVMEDIA_TYPE_VIDEO;
992 c->codec_type = CODEC_TYPE_VIDEO;
1029 #if LIBAVFORMAT_VERSION_MAJOR >= 56
1030 c->framerate = av_inv_q(c->time_base);
1032 st->avg_frame_rate = av_inv_q(c->time_base);
1037 c->max_b_frames = 10;
1038 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1040 c->max_b_frames = 2;
1041 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1047 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1048 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1049 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1051 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1055 const PixelFormat* supported_pixel_formats = codec->pix_fmts;
1056 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1059 c->pix_fmt = *supported_pixel_formats;
1060 ++supported_pixel_formats;
1065 if(fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
1069 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1070 if (strcmp(fmt->name,
"gif") != 0)
1073 oc->oformat->flags |= AVFMT_RAWPICTURE;
1082 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1083 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);
1085 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_video_stream (" + (
string)fmt->name +
" : " + (
string)av_get_pix_fmt_name(c->pix_fmt) +
")",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->pix_fmt", c->pix_fmt,
"oc->oformat->flags", oc->oformat->flags,
"", -1,
"", -1);
1092 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
1101 codec = avcodec_find_encoder_by_name(
info.acodec.c_str());
1103 codec = avcodec_find_encoder(audio_codec->codec_id);
1108 AVDictionary *opts = NULL;
1109 av_dict_set(&opts, "strict", "experimental", 0);
1112 if (avcodec_open2(audio_codec, codec, &opts) < 0)
1117 av_dict_free(&opts);
1121 if (audio_codec->frame_size <= 1) {
1127 case AV_CODEC_ID_PCM_S16LE:
1128 case AV_CODEC_ID_PCM_S16BE:
1129 case AV_CODEC_ID_PCM_U16LE:
1130 case AV_CODEC_ID_PCM_U16BE:
1131 audio_input_frame_size >>= 1;
1138 audio_input_frame_size = audio_codec->frame_size;
1142 initial_audio_input_frame_size = audio_input_frame_size;
1149 audio_outbuf =
new uint8_t[audio_outbuf_size];
1153 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1158 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1161 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_audio",
"audio_codec->thread_count", audio_codec->thread_count,
"audio_input_frame_size", audio_input_frame_size,
"buffer_size",
AVCODEC_MAX_AUDIO_FRAME_SIZE +
MY_INPUT_BUFFER_PADDING_SIZE,
"", -1,
"", -1,
"", -1);
1166 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
1172 video_codec->thread_count = min(FF_NUM_PROCESSORS, 16);
1175 codec = avcodec_find_encoder_by_name(
info.vcodec.c_str());
1182 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)
1183 video_codec->max_b_frames = 0;
1186 AVDictionary *opts = NULL;
1187 av_dict_set(&opts, "strict", "experimental", 0);
1190 if (avcodec_open2(video_codec, codec, &opts) < 0)
1195 av_dict_free(&opts);
1198 for(std::map<
string,
string>::iterator iter =
info.metadata.begin(); iter !=
info.metadata.end(); ++iter)
1200 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1203 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::open_video",
"video_codec->thread_count", video_codec->thread_count,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1208 void FFmpegWriter::write_audio_packets(
bool final)
1210 #pragma omp task firstprivate(final)
1213 int total_frame_samples = 0;
1214 int frame_position = 0;
1215 int channels_in_frame = 0;
1216 int sample_rate_in_frame = 0;
1217 int samples_in_frame = 0;
1222 int16_t* all_resampled_samples = NULL;
1223 int16_t* final_samples_planar = NULL;
1224 int16_t* final_samples = NULL;
1227 while (!queued_audio_frames.empty())
1230 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1233 sample_rate_in_frame = frame->SampleRate();
1234 samples_in_frame = frame->GetAudioSamplesCount();
1235 channels_in_frame = frame->GetAudioChannelsCount();
1236 channel_layout_in_frame = frame->ChannelsLayout();
1240 float* frame_samples_float = NULL;
1242 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1246 total_frame_samples = samples_in_frame * channels_in_frame;
1249 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
1251 all_queued_samples[frame_position] =
int(frame_samples_float[s] * (1 << 15));
1255 delete[] frame_samples_float;
1258 queued_audio_frames.pop_front();
1264 total_frame_samples = frame_position;
1265 int remaining_frame_samples = total_frame_samples;
1266 int samples_position = 0;
1269 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);
1272 AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
1274 AVFrame *audio_frame = NULL;
1279 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1282 avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples,
1283 audio_encoder_buffer_size, 0);
1286 switch (audio_codec->sample_fmt)
1288 case AV_SAMPLE_FMT_FLTP:
1290 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1293 case AV_SAMPLE_FMT_S32P:
1295 output_sample_fmt = AV_SAMPLE_FMT_S32;
1298 case AV_SAMPLE_FMT_S16P:
1300 output_sample_fmt = AV_SAMPLE_FMT_S16;
1303 case AV_SAMPLE_FMT_U8P:
1305 output_sample_fmt = AV_SAMPLE_FMT_U8;
1311 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1312 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1315 remaining_frame_samples = total_frame_samples;
1320 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1321 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1323 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);
1328 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1330 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1331 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1332 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1334 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1342 audio_converted->data,
1343 audio_converted->linesize[0],
1344 audio_converted->nb_samples,
1346 audio_frame->linesize[0],
1347 audio_frame->nb_samples);
1350 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)));
1353 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1356 av_freep(&(audio_frame->data[0]));
1358 av_freep(&audio_converted->data[0]);
1360 all_queued_samples = NULL;
1362 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);
1366 while (remaining_frame_samples > 0 ||
final) {
1368 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1372 if (remaining_frame_samples >= remaining_packet_samples)
1373 diff = remaining_packet_samples;
1374 else if (remaining_frame_samples < remaining_packet_samples)
1375 diff = remaining_frame_samples;
1380 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));
1383 audio_input_position += diff;
1384 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1385 remaining_frame_samples -= diff;
1386 remaining_packet_samples -= diff;
1389 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !
final)
1396 if (av_sample_fmt_is_planar(audio_codec->sample_fmt))
1398 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);
1405 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1406 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec->sample_fmt, 0);
1409 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1410 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1417 audio_frame->nb_samples = audio_input_position /
info.
channels;
1420 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)));
1423 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1426 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt, (uint8_t *) final_samples_planar,
1427 audio_encoder_buffer_size, 0);
1430 frame_final->nb_samples = audio_input_frame_size;
1431 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels, frame_final->nb_samples, audio_codec->sample_fmt, 0);
1436 frame_final->linesize[0],
1437 frame_final->nb_samples,
1439 audio_frame->linesize[0],
1440 audio_frame->nb_samples);
1444 memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) *
info.
channels);
1447 av_freep(&(audio_frame->data[0]));
1449 all_queued_samples = NULL;
1451 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
"nb_samples", nb_samples,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1455 final_samples = (int16_t*)av_malloc(
sizeof(int16_t) * audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)));
1458 memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
1461 frame_final->nb_samples = audio_input_frame_size;
1464 avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
1465 audio_encoder_buffer_size, 0);
1469 write_audio_count += FFMIN(audio_input_frame_size, audio_input_position);
1470 frame_final->pts = write_audio_count;
1474 av_init_packet(&pkt);
1475 pkt.data = audio_encoder_buffer;
1476 pkt.size = audio_encoder_buffer_size;
1479 pkt.pts = pkt.dts = write_audio_count;
1482 int got_packet_ptr = 0;
1488 int frame_finished = 0;
1489 error_code = ret = avcodec_send_frame(audio_codec, frame_final);
1490 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1491 avcodec_send_frame(audio_codec, NULL);
1496 ret = avcodec_receive_packet(audio_codec, &pkt);
1499 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1500 avcodec_flush_buffers(audio_codec);
1504 ret = frame_finished;
1507 if (!pkt.data && !frame_finished)
1511 got_packet_ptr = ret;
1514 int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
1517 if (error_code == 0 && got_packet_ptr) {
1521 pkt.pts = pkt.dts = write_audio_count;
1524 if (pkt.pts != AV_NOPTS_VALUE)
1525 pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
1526 if (pkt.dts != AV_NOPTS_VALUE)
1527 pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
1528 if (pkt.duration > 0)
1529 pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
1532 pkt.stream_index = audio_st->index;
1533 pkt.flags |= AV_PKT_FLAG_KEY;
1536 int error_code = av_interleaved_write_frame(oc, &pkt);
1539 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1545 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1549 av_freep(&(frame_final->data[0]));
1556 audio_input_position = 0;
1561 if (all_resampled_samples) {
1562 av_freep(&all_resampled_samples);
1563 all_resampled_samples = NULL;
1565 if (all_queued_samples) {
1566 av_freep(&all_queued_samples);
1567 all_queued_samples = NULL;
1574 AVFrame* FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer)
1577 AVFrame *new_av_frame = NULL;
1581 if (new_av_frame == NULL)
1582 throw OutOfMemory(
"Could not allocate AVFrame", path);
1591 new_buffer = (uint8_t*)av_malloc(*buffer_size *
sizeof(uint8_t));
1594 new_av_frame->width = width;
1595 new_av_frame->height = height;
1596 new_av_frame->format = pix_fmt;
1600 return new_av_frame;
1604 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
1607 int source_image_width = frame->GetWidth();
1608 int source_image_height = frame->GetHeight();
1611 if (source_image_height == 1 && source_image_width == 1)
1615 if (image_rescalers.size() == 0)
1616 InitScalers(source_image_width, source_image_height);
1619 SwsContext *scaler = image_rescalers[rescaler_position];
1620 rescaler_position++;
1621 if (rescaler_position == num_of_rescalers)
1622 rescaler_position = 0;
1624 #pragma omp task firstprivate(frame, scaler, source_image_width, source_image_height)
1627 int bytes_source = 0;
1628 int bytes_final = 0;
1629 AVFrame *frame_source = NULL;
1630 const uchar *pixels = NULL;
1633 pixels = frame->GetPixels();
1636 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
1638 AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format),
info.
width,
info.
height, &bytes_final, NULL);
1640 AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1645 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::process_video_packet",
"frame->number", frame->number,
"bytes_source", bytes_source,
"bytes_final", bytes_final,
"", -1,
"", -1,
"", -1);
1648 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1649 source_image_height, frame_final->data, frame_final->linesize);
1652 #pragma omp critical (av_frames_section)
1653 add_avframe(frame, frame_final);
1663 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* frame_final)
1665 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1666 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet",
"frame->number", frame->number,
"oc->oformat->flags", oc->oformat->flags,
"", -1,
"", -1,
"", -1,
"", -1);
1668 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);
1670 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1673 av_init_packet(&pkt);
1675 pkt.flags |= AV_PKT_FLAG_KEY;
1676 pkt.stream_index= video_st->index;
1677 pkt.data= (uint8_t*)frame_final->data;
1678 pkt.size=
sizeof(AVPicture);
1681 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1682 pkt.pts = write_video_count;
1685 int error_code = av_interleaved_write_frame(oc, &pkt);
1688 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1700 av_init_packet(&pkt);
1703 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
1706 uint8_t *video_outbuf = NULL;
1709 write_video_count += av_rescale_q(1, (AVRational){
info.
fps.
den,
info.
fps.
num}, video_codec->time_base);
1712 frame_final->pts = write_video_count;
1715 int got_packet_ptr = 0;
1719 int frameFinished = 0;
1720 int ret = avcodec_send_frame(video_codec, frame_final);
1723 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet (Frame not sent)",
"", -1,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1724 if (ret == AVERROR(EAGAIN) )
1725 cerr <<
"Frame EAGAIN" <<
"\n";
1726 if (ret == AVERROR_EOF )
1727 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1728 avcodec_send_frame(video_codec, NULL);
1732 ret = avcodec_receive_packet(video_codec, &pkt);
1733 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1734 avcodec_flush_buffers(video_codec);
1745 #if LIBAVFORMAT_VERSION_MAJOR >= 54
1747 error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
1748 if (error_code != 0 )
1749 cerr <<
"Frame AVERROR_EOF" <<
"\n";
1750 if (got_packet_ptr == 0 )
1751 cerr <<
"Frame gotpacket error" <<
"\n";
1754 int video_outbuf_size = 200000;
1755 video_outbuf = (uint8_t*) av_malloc(200000);
1758 int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
1762 if(video_codec->coded_frame->key_frame)
1763 pkt.flags |= AV_PKT_FLAG_KEY;
1764 pkt.data= video_outbuf;
1774 if (error_code == 0 && got_packet_ptr) {
1781 if (pkt.pts != AV_NOPTS_VALUE)
1782 pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
1783 if (pkt.dts != AV_NOPTS_VALUE)
1784 pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
1785 if (pkt.duration > 0)
1786 pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
1787 pkt.stream_index = video_st->index;
1790 int error_code = av_interleaved_write_frame(oc, &pkt);
1793 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR [" + (
string)
av_err2str(error_code) +
"]",
"error_code", error_code,
"", -1,
"", -1,
"", -1,
"", -1,
"", -1);
1800 delete[] video_outbuf;
1814 av_dump_format(oc, 0, path.c_str(), 1);
1818 void FFmpegWriter::InitScalers(
int source_width,
int source_height)
1820 int scale_mode = SWS_FAST_BILINEAR;
1822 scale_mode = SWS_LANCZOS;
1826 for (
int x = 0; x < num_of_rescalers; x++)
1829 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
info.
width,
info.
height,
AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), scale_mode, NULL, NULL, NULL);
1832 image_rescalers.push_back(img_convert_ctx);
1838 original_sample_rate = sample_rate;
1839 original_channels = channels;
1846 for (
int x = 0; x < num_of_rescalers; x++)
1847 sws_freeContext(image_rescalers[x]);
1850 image_rescalers.clear();
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
A video stream (used to determine which type of stream)
#define AV_FREE_FRAME(av_frame)
void SetOption(StreamType stream, string name, string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
int num
Numerator for the fraction.
WriterInfo info
Information about the current media file.
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
An audio stream (used to determine which type of stream)
int video_bit_rate
The bit rate of the video stream (in bytes)
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Exception when an invalid # of audio channels are detected.
#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height)
std::map< string, string > metadata
An optional map/dictionary of video & audio metadata.
string acodec
The name of the audio codec used to encode / decode the video stream.
#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
string vcodec
The name of the video codec used to encode / decode the video stream.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in)
#define AV_OPTION_FIND(priv_data, name)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
This abstract class is the base class, used by all readers in libopenshot.
int width
The width of the video (in pixels)
int audio_bit_rate
The bit rate of the audio stream (in bytes)
#define OPEN_MP_NUM_PROCESSORS
void WriteFrame(std::shared_ptr< Frame > frame)
Add a frame to the stack waiting to be encoded.
Exception when encoding audio packet.
Exception when invalid sample rate is detected during encoding.
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
void SetVideoOptions(bool has_video, string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
virtual std::shared_ptr< Frame > GetFrame(int64_t number)=0
#define AV_FREE_CONTEXT(av_context)
Exception when no valid codec is found for a file.
Exception when memory could not be allocated.
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
Exception when invalid encoding options are used.
#define FF_NUM_PROCESSORS
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Exception for files that can not be found or opened.
FFmpegWriter(string path)
Constructor for FFmpegWriter. Throws one of the following exceptions.
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information.
This class represents a fraction.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
static bool IsValidCodec(string codec_name)
Determine if codec name is valid.
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
#define av_err2str(errnum)
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
void Close()
Close the writer.
bool interlaced_frame
Are the contents of this frame interlaced.
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
#define MY_INPUT_BUFFER_PADDING_SIZE
#define AV_GET_IMAGE_SIZE(pix_fmt, width, height)
#define AV_OUTPUT_CONTEXT(output_context, path)
bool has_video
Determines if this file has a video stream.
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
#define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count)
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
bool has_audio
Determines if this file has an audio stream.
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate)
Set audio export options.
Exception when a writer is closed, and a frame is requested.
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
int height
The height of the video (in pixels)
int den
Denominator for the fraction.
#define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st)
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)
#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)