34 #include "libavutil/opt.h"
35 #include "libavutil/samplefmt.h"
36 #include "libavutil/imgutils.h"
39 #define LOC QString("AVFW(%1): ").arg(m_filename)
40 #define LOC_ERR QString("AVFW(%1) Error: ").arg(m_filename)
41 #define LOC_WARN QString("AVFW(%1) Warning: ").arg(m_filename)
47 av_write_trailer(
m_ctx);
48 avio_closep(&
m_ctx->pb);
49 for(
uint i = 0; i <
m_ctx->nb_streams; i++)
50 av_freep(&
m_ctx->streams[i]);
64 AVOutputFormat *fmt = av_guess_format(
m_container.toLatin1().constData(),
nullptr,
nullptr);
67 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to guess AVOutputFormat from container %1")
79 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to find video codec %1")
87 m_fmt.video_codec = AV_CODEC_ID_NONE;
93 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to find audio codec %1")
100 m_ctx = avformat_alloc_context();
103 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): Unable to allocate AVFormatContext");
110 m_ctx->packet_size = 2324;
113 auto size =
static_cast<size_t>(
filename.size());
114 m_ctx->url =
static_cast<char*
>(av_malloc(size));
117 if (
m_fmt.video_codec != AV_CODEC_ID_NONE)
119 if (
m_fmt.audio_codec != AV_CODEC_ID_NONE)
124 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): OpenVideo() failed");
130 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): OpenAudio() failed");
139 if (!(
m_fmt.flags & AVFMT_NOFILE))
141 if (avio_open(&
m_ctx->pb,
m_filename.toLatin1().constData(), AVIO_FLAG_WRITE) < 0)
143 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenFile(): avio_open() failed");
152 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"OpenFile(): RingBuffer::Create() failed: '%1'")
159 auto *url =
reinterpret_cast<URLContext*
>(
m_ctx->pb->opaque);
163 if (avformat_write_header(
m_ctx,
nullptr) < 0)
175 avio_closep(&
m_ctx->pb);
186 av_write_trailer(
m_ctx);
187 avio_close(
m_ctx->pb);
188 for(
uint i = 0; i <
m_ctx->nb_streams; i++)
189 av_freep(&
m_ctx->streams[i]);
213 AVPacket *pkt = av_packet_alloc();
216 LOG(VB_RECORD, LOG_ERR,
"packet allocation failed");
217 return AVERROR(ENOMEM);
222 int ret = avcodec_encode_video2(avctx, pkt,
m_picture, &got_pkt);
226 LOG(VB_RECORD, LOG_ERR,
"avcodec_encode_video2() failed");
227 av_packet_free(&pkt);
233 av_packet_free(&pkt);
237 std::chrono::milliseconds tc =
Frame->m_timecode;
245 if (pict_type == AV_PICTURE_TYPE_I)
246 pkt->flags |= AV_PKT_FLAG_KEY;
254 pkt->dts = AV_NOPTS_VALUE;
257 ret = av_interleaved_write_frame(
m_ctx, pkt);
259 LOG(VB_RECORD, LOG_ERR,
LOC +
"WriteVideoFrame(): av_interleaved_write_frame couldn't write Video");
263 av_packet_unref(pkt);
264 av_packet_free(&pkt);
270 #if (Q_BYTE_ORDER == Q_BIG_ENDIAN)
273 buf16[i] = qFromLittleEndian<quint16>(buf16[i]);
282 AVPacket *pkt = av_packet_alloc();
285 LOG(VB_RECORD, LOG_ERR,
"packet allocation failed");
286 return AVERROR(ENOMEM);
289 if (av_get_packed_sample_fmt(avctx->sample_fmt) == AV_SAMPLE_FMT_FLT)
292 static_cast<void*
>(
Buffer), samples_per_avframe * sampleSizeIn);
295 if (av_sample_fmt_is_planar(avctx->sample_fmt))
299 samples_per_avframe * sampleSizeOut);
320 bool got_packet =
false;
321 int ret = avcodec_receive_packet(avctx, pkt);
324 if (ret == AVERROR(EAGAIN))
335 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"audio encode error: %1 (%2)")
337 av_packet_free(&pkt);
343 av_packet_free(&pkt);
347 std::chrono::milliseconds tc = Timecode;
361 pkt->dts = AV_NOPTS_VALUE;
362 pkt->flags |= AV_PKT_FLAG_KEY;
365 ret = av_interleaved_write_frame(
m_ctx, pkt);
367 LOG(VB_RECORD, LOG_ERR,
LOC +
"WriteAudioFrame(): av_interleaved_write_frame couldn't write Audio");
370 av_packet_unref(pkt);
371 av_packet_free(&pkt);
376 std::chrono::milliseconds ,
int )
401 AVStream *stream = avformat_new_stream(
m_ctx,
nullptr);
404 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddVideoStream(): avformat_new_stream() failed");
409 stream->time_base.den = 90000;
410 stream->time_base.num = 1;
411 stream->r_frame_rate.num = 0;
412 stream->r_frame_rate.den = 0;
414 AVCodec *codec = avcodec_find_encoder(
m_ctx->oformat->video_codec);
417 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddVideoStream(): avcodec_find_encoder() failed");
423 context->codec = codec;
424 context->codec_id =
m_ctx->oformat->video_codec;
425 context->codec_type = AVMEDIA_TYPE_VIDEO;
435 context->pix_fmt = AV_PIX_FMT_YUV420P;
437 context->thread_type = FF_THREAD_SLICE;
439 if (context->codec_id == AV_CODEC_ID_MPEG2VIDEO)
441 context->max_b_frames = 2;
443 else if (context->codec_id == AV_CODEC_ID_MPEG1VIDEO)
445 context->mb_decision = 2;
447 else if (context->codec_id == AV_CODEC_ID_H264)
453 if ((context->height > 720) ||
454 (context->bit_rate > 1400000))
458 av_opt_set(context->priv_data,
"profile",
"main", 0);
460 else if ((context->height > 576) ||
461 (context->bit_rate > 1000000))
465 av_opt_set(context->priv_data,
"profile",
"baseline", 0);
471 av_opt_set(context->priv_data,
"profile",
"baseline", 0);
476 av_opt_set_int(context,
"coder", FF_CODER_TYPE_VLC, 0);
477 context->max_b_frames = 0;
479 context->flags |= AV_CODEC_FLAG_LOOP_FILTER;
480 context->me_cmp |= 1;
483 av_opt_set(context,
"me_method",
"hex", 0);
484 context->me_subpel_quality = 6;
485 context->me_range = 16;
486 context->keyint_min = 25;
488 av_opt_set_int(context,
"sc_threshold", 40, 0);
489 context->i_quant_factor = 0.71F;
491 av_opt_set_int(context,
"b_strategy", 1, 0);
492 context->qcompress = 0.6F;
495 context->max_qdiff = 4;
497 context->trellis = 0;
500 av_opt_set(context,
"partitions",
"i8x8,i4x4,p8x8,b8x8", 0);
501 av_opt_set_int(context,
"direct-pred", 1, 0);
502 av_opt_set_int(context,
"rc-lookahead", 0, 0);
503 av_opt_set_int(context,
"fast-pskip", 1, 0);
504 av_opt_set_int(context,
"mixed-refs", 1, 0);
505 av_opt_set_int(context,
"8x8dct", 0, 0);
506 av_opt_set_int(context,
"weightb", 0, 0);
509 av_opt_set(context->priv_data,
"preset",
m_encodingPreset.toLatin1().constData(), 0);
510 av_opt_set(context->priv_data,
"tune",
m_encodingTune.toLatin1().constData(), 0);
513 if(
m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
514 context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
525 if (avcodec_open2(context,
nullptr,
nullptr) < 0)
527 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenVideo(): avcodec_open() failed");
536 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenVideo(): AllocPicture() failed");
550 AVStream *stream = avformat_new_stream(
m_ctx,
nullptr);
553 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddAudioStream(): avformat_new_stream() failed");
560 context->codec_id =
m_ctx->oformat->audio_codec;
561 context->codec_type = AVMEDIA_TYPE_AUDIO;
565 context->channel_layout =
static_cast<uint64_t
>(av_get_default_channel_layout(
m_audioChannels));
573 stream->time_base.den = 90000;
574 stream->time_base.num = 1;
577 if (
m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
578 context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
585 if (Codec->sample_fmts)
587 for (
int i = 0; Codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
589 if (av_get_packed_sample_fmt(Codec->sample_fmts[i]) ==
Format)
591 Ctx->sample_fmt = Codec->sample_fmts[i];
602 context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
604 AVCodec *codec = avcodec_find_encoder(context->codec_id);
607 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): avcodec_find_encoder() failed");
617 if (avcodec_open2(context, codec,
nullptr) < 0)
619 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): avcodec_open() failed");
628 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): alloc_frame() failed");
633 av_get_bytes_per_sample(context->sample_fmt));
634 if (av_get_packed_sample_fmt(context->sample_fmt) == AV_SAMPLE_FMT_FLT)
637 if (!(
m_audioInBuf =
static_cast<unsigned char*
>(av_malloc(size))))
641 if (av_sample_fmt_is_planar(context->sample_fmt))
644 if (!(
m_audioInPBuf =
static_cast<unsigned char*
>(av_malloc(size))))
652 AVFrame *picture = av_frame_alloc();
655 LOG(VB_RECORD, LOG_ERR,
LOC +
"AllocPicture failed");
659 int size = av_image_get_buffer_size(PixFmt,
m_width,
m_height, IMAGE_ALIGN);
660 auto *buffer =
static_cast<unsigned char*
>(av_malloc(
static_cast<size_t>(size)));
663 LOG(VB_RECORD, LOG_ERR,
LOC +
"AllocPicture(): av_malloc() failed");
664 av_frame_free(&picture);
668 av_image_fill_arrays(picture->data, picture->linesize, buffer, PixFmt,
m_width,
m_height, IMAGE_ALIGN);
675 result.den =
static_cast<int>(floor(
m_frameRate * 100));
681 AVRational req = { result.den, result.num };
682 const AVRational *best =
nullptr;
683 AVRational best_error= { INT_MAX, 1 };
684 for (; rates->den != 0; rates++)
686 AVRational
error = av_sub_q(req, *rates);
689 if (av_cmp_q(
error, best_error) < 0)
696 if (best && best->num && best->den)
698 result.den = best->num;
699 result.num = best->den;
703 if (result.den == 2997)
708 else if (result.den == 5994)