36 #include "libavutil/opt.h"
37 #include "libavutil/samplefmt.h"
38 #include "libavutil/imgutils.h"
41 #define LOC QString("AVFW(%1): ").arg(m_filename)
42 #define LOC_ERR QString("AVFW(%1) Error: ").arg(m_filename)
43 #define LOC_WARN QString("AVFW(%1) Warning: ").arg(m_filename)
49 av_write_trailer(
m_ctx);
50 avio_closep(&
m_ctx->pb);
51 for(
uint i = 0; i <
m_ctx->nb_streams; i++)
52 av_freep(&
m_ctx->streams[i]);
66 const AVOutputFormat *fmt = av_guess_format(
m_container.toLatin1().constData(),
nullptr,
nullptr);
69 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to guess AVOutputFormat from container %1")
81 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to find video codec %1")
89 m_fmt.video_codec = AV_CODEC_ID_NONE;
95 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Init(): Unable to find audio codec %1")
102 m_ctx = avformat_alloc_context();
105 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): Unable to allocate AVFormatContext");
112 m_ctx->packet_size = 2324;
115 auto size =
static_cast<size_t>(
filename.size());
116 m_ctx->url =
static_cast<char*
>(av_malloc(size));
119 if (
m_fmt.video_codec != AV_CODEC_ID_NONE)
121 if (
m_fmt.audio_codec != AV_CODEC_ID_NONE)
126 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): OpenVideo() failed");
132 LOG(VB_RECORD, LOG_ERR,
LOC +
"Init(): OpenAudio() failed");
141 if (!(
m_fmt.flags & AVFMT_NOFILE))
143 if (avio_open(&
m_ctx->pb,
m_filename.toLatin1().constData(), AVIO_FLAG_WRITE) < 0)
145 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenFile(): avio_open() failed");
154 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"OpenFile(): RingBuffer::Create() failed: '%1'")
161 auto *url =
reinterpret_cast<URLContext*
>(
m_ctx->pb->opaque);
165 if (avformat_write_header(
m_ctx,
nullptr) < 0)
177 avio_closep(&
m_ctx->pb);
188 av_write_trailer(
m_ctx);
189 avio_close(
m_ctx->pb);
190 for(
uint i = 0; i <
m_ctx->nb_streams; i++)
191 av_freep(&
m_ctx->streams[i]);
215 AVPacket *pkt = av_packet_alloc();
218 LOG(VB_RECORD, LOG_ERR,
"packet allocation failed");
219 return AVERROR(ENOMEM);
228 bool got_packet =
false;
229 int ret = avcodec_receive_packet(avctx, pkt);
232 if (ret == AVERROR(EAGAIN))
235 ret = avcodec_send_frame(avctx,
m_picture);
243 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"video encode error: %1 (%2)")
245 av_packet_free(&pkt);
251 av_packet_free(&pkt);
255 std::chrono::milliseconds tc =
Frame->m_timecode;
263 if (pict_type == AV_PICTURE_TYPE_I)
264 pkt->flags |= AV_PKT_FLAG_KEY;
272 pkt->dts = AV_NOPTS_VALUE;
275 ret = av_interleaved_write_frame(
m_ctx, pkt);
277 LOG(VB_RECORD, LOG_ERR,
LOC +
"WriteVideoFrame(): av_interleaved_write_frame couldn't write Video");
281 av_packet_unref(pkt);
282 av_packet_free(&pkt);
288 #if (Q_BYTE_ORDER == Q_BIG_ENDIAN)
291 buf16[i] = qFromLittleEndian<quint16>(buf16[i]);
300 AVPacket *pkt = av_packet_alloc();
303 LOG(VB_RECORD, LOG_ERR,
"packet allocation failed");
304 return AVERROR(ENOMEM);
307 if (av_get_packed_sample_fmt(avctx->sample_fmt) == AV_SAMPLE_FMT_FLT)
310 static_cast<void*
>(
Buffer), samples_per_avframe * sampleSizeIn);
313 if (av_sample_fmt_is_planar(avctx->sample_fmt))
317 samples_per_avframe * sampleSizeOut);
338 bool got_packet =
false;
339 int ret = avcodec_receive_packet(avctx, pkt);
342 if (ret == AVERROR(EAGAIN))
353 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"audio encode error: %1 (%2)")
355 av_packet_free(&pkt);
361 av_packet_free(&pkt);
365 std::chrono::milliseconds tc = Timecode;
379 pkt->dts = AV_NOPTS_VALUE;
380 pkt->flags |= AV_PKT_FLAG_KEY;
383 ret = av_interleaved_write_frame(
m_ctx, pkt);
385 LOG(VB_RECORD, LOG_ERR,
LOC +
"WriteAudioFrame(): av_interleaved_write_frame couldn't write Audio");
388 av_packet_unref(pkt);
389 av_packet_free(&pkt);
394 std::chrono::milliseconds ,
int )
419 AVStream *stream = avformat_new_stream(
m_ctx,
nullptr);
422 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddVideoStream(): avformat_new_stream() failed");
427 stream->time_base.den = 90000;
428 stream->time_base.num = 1;
429 stream->r_frame_rate.num = 0;
430 stream->r_frame_rate.den = 0;
432 const AVCodec *codec = avcodec_find_encoder(
m_ctx->oformat->video_codec);
435 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddVideoStream(): avcodec_find_encoder() failed");
441 context->codec = codec;
442 context->codec_id =
m_ctx->oformat->video_codec;
443 context->codec_type = AVMEDIA_TYPE_VIDEO;
453 context->pix_fmt = AV_PIX_FMT_YUV420P;
455 context->thread_type = FF_THREAD_SLICE;
457 if (context->codec_id == AV_CODEC_ID_MPEG2VIDEO)
459 context->max_b_frames = 2;
461 else if (context->codec_id == AV_CODEC_ID_MPEG1VIDEO)
463 context->mb_decision = 2;
465 else if (context->codec_id == AV_CODEC_ID_H264)
471 if ((context->height > 720) ||
472 (context->bit_rate > 1400000))
476 av_opt_set(context->priv_data,
"profile",
"main", 0);
478 else if ((context->height > 576) ||
479 (context->bit_rate > 1000000))
483 av_opt_set(context->priv_data,
"profile",
"baseline", 0);
489 av_opt_set(context->priv_data,
"profile",
"baseline", 0);
493 context->max_b_frames = 0;
495 context->flags |= AV_CODEC_FLAG_LOOP_FILTER;
496 context->me_cmp |= 1;
499 av_opt_set(context,
"me_method",
"hex", 0);
500 context->me_subpel_quality = 6;
501 context->me_range = 16;
502 context->keyint_min = 25;
504 av_opt_set_int(context,
"sc_threshold", 40, 0);
505 context->i_quant_factor = 0.71F;
507 av_opt_set_int(context,
"b_strategy", 1, 0);
508 context->qcompress = 0.6F;
511 context->max_qdiff = 4;
513 context->trellis = 0;
516 av_opt_set(context,
"partitions",
"i8x8,i4x4,p8x8,b8x8", 0);
517 av_opt_set_int(context,
"direct-pred", 1, 0);
518 av_opt_set_int(context,
"rc-lookahead", 0, 0);
519 av_opt_set_int(context,
"fast-pskip", 1, 0);
520 av_opt_set_int(context,
"mixed-refs", 1, 0);
521 av_opt_set_int(context,
"8x8dct", 0, 0);
522 av_opt_set_int(context,
"weightb", 0, 0);
525 av_opt_set(context->priv_data,
"preset",
m_encodingPreset.toLatin1().constData(), 0);
526 av_opt_set(context->priv_data,
"tune",
m_encodingTune.toLatin1().constData(), 0);
529 if(
m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
530 context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
541 if (avcodec_open2(context,
nullptr,
nullptr) < 0)
543 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenVideo(): avcodec_open() failed");
552 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenVideo(): AllocPicture() failed");
566 AVStream *stream = avformat_new_stream(
m_ctx,
nullptr);
569 LOG(VB_RECORD, LOG_ERR,
LOC +
"AddAudioStream(): avformat_new_stream() failed");
576 context->codec_id =
m_ctx->oformat->audio_codec;
577 context->codec_type = AVMEDIA_TYPE_AUDIO;
588 stream->time_base.den = 90000;
589 stream->time_base.num = 1;
592 if (
m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
593 context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
600 if (Codec->sample_fmts)
602 for (
int i = 0; Codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
604 if (av_get_packed_sample_fmt(Codec->sample_fmts[i]) ==
Format)
606 Ctx->sample_fmt = Codec->sample_fmts[i];
617 context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
619 const AVCodec *codec = avcodec_find_encoder(context->codec_id);
622 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): avcodec_find_encoder() failed");
632 if (avcodec_open2(context, codec,
nullptr) < 0)
634 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): avcodec_open() failed");
643 LOG(VB_RECORD, LOG_ERR,
LOC +
"OpenAudio(): alloc_frame() failed");
648 av_get_bytes_per_sample(context->sample_fmt);
649 if (av_get_packed_sample_fmt(context->sample_fmt) == AV_SAMPLE_FMT_FLT)
652 if (!(
m_audioInBuf =
static_cast<unsigned char*
>(av_malloc(size))))
656 if (av_sample_fmt_is_planar(context->sample_fmt))
659 if (!(
m_audioInPBuf =
static_cast<unsigned char*
>(av_malloc(size))))
667 AVFrame *picture = av_frame_alloc();
670 LOG(VB_RECORD, LOG_ERR,
LOC +
"AllocPicture failed");
674 int size = av_image_get_buffer_size(PixFmt,
m_width,
m_height, IMAGE_ALIGN);
675 auto *buffer =
static_cast<unsigned char*
>(av_malloc(
static_cast<size_t>(size)));
678 LOG(VB_RECORD, LOG_ERR,
LOC +
"AllocPicture(): av_malloc() failed");
679 av_frame_free(&picture);
683 av_image_fill_arrays(picture->data, picture->linesize, buffer, PixFmt,
m_width,
m_height, IMAGE_ALIGN);
690 result.den =
static_cast<int>(floor(
m_frameRate * 100));
696 AVRational req = { result.den, result.num };
697 const AVRational *best =
nullptr;
698 AVRational best_error= { INT_MAX, 1 };
699 for (; rates->den != 0; rates++)
701 AVRational
error = av_sub_q(req, *rates);
704 if (av_cmp_q(
error, best_error) < 0)
711 if (best && best->num && best->den)
713 result.den = best->num;
714 result.num = best->den;
718 if (result.den == 2997)
723 else if (result.den == 5994)