MythTV  master
mythavformatwriter.cpp
Go to the documentation of this file.
1 /*
2  * Class AVFormatWriter
3  *
4  * Copyright (C) Chris Pinkham 2011
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 #include "io/mythavformatwriter.h"
21 
22 #include <limits> // workaround QTBUG-90395
23 
24 #include <QtGlobal>
25 #include <QtEndian>
26 
27 // MythTV
31 #include "mythavutil.h"
32 
33 
34 // FFmpeg
35 extern "C" {
36 #include "libavutil/opt.h"
37 #include "libavutil/samplefmt.h"
38 #include "libavutil/imgutils.h"
39 }
40 
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)
44 
46 {
47  if (m_ctx)
48  {
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]);
53  av_freep(&m_ctx);
54  }
55 
56  av_freep(&m_audioInBuf);
57  av_freep(&m_audioInPBuf);
58  if (m_audPicture)
59  av_frame_free(&m_audPicture);
60  Cleanup();
61  av_frame_free(&m_picture);
62 }
63 
65 {
66  const AVOutputFormat *fmt = av_guess_format(m_container.toLatin1().constData(), nullptr, nullptr);
67  if (!fmt)
68  {
69  LOG(VB_RECORD, LOG_ERR, LOC + QString("Init(): Unable to guess AVOutputFormat from container %1")
70  .arg(m_container));
71  return false;
72  }
73 
74  m_fmt = *fmt;
75 
76  if (m_width && m_height)
77  {
78  m_avVideoCodec = avcodec_find_encoder_by_name(m_videoCodec.toLatin1().constData());
79  if (!m_avVideoCodec)
80  {
81  LOG(VB_RECORD, LOG_ERR, LOC + QString("Init(): Unable to find video codec %1")
82  .arg(m_videoCodec));
83  return false;
84  }
85  m_fmt.video_codec = m_avVideoCodec->id;
86  }
87  else
88  {
89  m_fmt.video_codec = AV_CODEC_ID_NONE;
90  }
91 
92  m_avAudioCodec = avcodec_find_encoder_by_name(m_audioCodec.toLatin1().constData());
93  if (!m_avAudioCodec)
94  {
95  LOG(VB_RECORD, LOG_ERR, LOC + QString("Init(): Unable to find audio codec %1")
96  .arg(m_audioCodec));
97  return false;
98  }
99 
100  m_fmt.audio_codec = m_avAudioCodec->id;
101 
102  m_ctx = avformat_alloc_context();
103  if (!m_ctx)
104  {
105  LOG(VB_RECORD, LOG_ERR, LOC + "Init(): Unable to allocate AVFormatContext");
106  return false;
107  }
108 
109  m_ctx->oformat = &m_fmt;
110 
111  if (m_container == "mpegts")
112  m_ctx->packet_size = 2324;
113 
114  QByteArray filename = m_filename.toLatin1();
115  auto size = static_cast<size_t>(filename.size());
116  m_ctx->url = static_cast<char*>(av_malloc(size));
117  memcpy(m_ctx->url, filename.constData(), size);
118 
119  if (m_fmt.video_codec != AV_CODEC_ID_NONE)
121  if (m_fmt.audio_codec != AV_CODEC_ID_NONE)
123 
124  if (m_videoStream && !OpenVideo())
125  {
126  LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenVideo() failed");
127  return false;
128  }
129 
130  if (m_audioStream && !OpenAudio())
131  {
132  LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenAudio() failed");
133  return false;
134  }
135 
136  return true;
137 }
138 
140 {
141  if (!(m_fmt.flags & AVFMT_NOFILE))
142  {
143  if (avio_open(&m_ctx->pb, m_filename.toLatin1().constData(), AVIO_FLAG_WRITE) < 0)
144  {
145  LOG(VB_RECORD, LOG_ERR, LOC + "OpenFile(): avio_open() failed");
146  return false;
147  }
148  }
149 
151 
152  if (!m_buffer || !m_buffer->GetLastError().isEmpty())
153  {
154  LOG(VB_RECORD, LOG_ERR, LOC + QString("OpenFile(): RingBuffer::Create() failed: '%1'")
155  .arg(m_buffer ? m_buffer->GetLastError() : ""));
156  Cleanup();
157  return false;
158  }
159 
161  auto *url = reinterpret_cast<URLContext*>(m_ctx->pb->opaque);
163  url->priv_data = static_cast<void*>(m_avfBuffer);
164 
165  if (avformat_write_header(m_ctx, nullptr) < 0)
166  {
167  Cleanup();
168  return false;
169  }
170 
171  return true;
172 }
173 
175 {
176  if (m_ctx && m_ctx->pb)
177  avio_closep(&m_ctx->pb);
178  delete m_avfBuffer;
179  m_avfBuffer = nullptr;
180  delete m_buffer;
181  m_buffer = nullptr;
182 }
183 
185 {
186  if (m_ctx)
187  {
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]);
192  av_freep(&m_ctx);
193  }
194  return true;
195 }
196 
198 {
199  return (m_bufferedVideoFrameTypes.isEmpty()) ||
200  (m_bufferedVideoFrameTypes.first() == AV_PICTURE_TYPE_I);
201 }
202 
204 {
205  long long framesEncoded = m_framesWritten + m_bufferedVideoFrameTimes.size();
206 
207  av_frame_unref(m_picture);
209  m_picture->pts = framesEncoded + 1;
210  m_picture->pict_type = ((framesEncoded % m_keyFrameDist) == 0) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
211 
212  m_bufferedVideoFrameTimes.push_back(Frame->m_timecode);
213  m_bufferedVideoFrameTypes.push_back(m_picture->pict_type);
214 
215  AVPacket *pkt = av_packet_alloc();
216  if (pkt == nullptr)
217  {
218  LOG(VB_RECORD, LOG_ERR, "packet allocation failed");
219  return AVERROR(ENOMEM);
220  }
221 
222  AVCodecContext *avctx = m_codecMap.GetCodecContext(m_videoStream);
223 
224  // SUGGESTION
225  // Now that avcodec_encode_video2 is removed and replaced
226  // by 2 calls, this could be optimized
227  // into separate routines or separate threads.
228  bool got_packet = false;
229  int ret = avcodec_receive_packet(avctx, pkt);
230  if (ret == 0)
231  got_packet = true;
232  if (ret == AVERROR(EAGAIN))
233  ret = 0;
234  if (ret == 0)
235  ret = avcodec_send_frame(avctx, m_picture);
236  // if ret from avcodec_send_frame is AVERROR(EAGAIN) then
237  // there are 2 packets to be received while only 1 frame to be
238  // sent. The code does not cater for this. Hopefully it will not happen.
239 
240  if (ret < 0)
241  {
242  std::string error;
243  LOG(VB_GENERAL, LOG_ERR, LOC + QString("video encode error: %1 (%2)")
244  .arg(av_make_error_stdstring(error, ret)).arg(got_packet));
245  av_packet_free(&pkt);
246  return ret;
247  }
248 
249  if (!got_packet)
250  {
251  av_packet_free(&pkt);
252  return ret;
253  }
254 
255  std::chrono::milliseconds tc = Frame->m_timecode;
256 
257  if (!m_bufferedVideoFrameTimes.isEmpty())
258  tc = m_bufferedVideoFrameTimes.takeFirst();
259 
260  if (!m_bufferedVideoFrameTypes.isEmpty())
261  {
262  int pict_type = m_bufferedVideoFrameTypes.takeFirst();
263  if (pict_type == AV_PICTURE_TYPE_I)
264  pkt->flags |= AV_PKT_FLAG_KEY;
265  }
266 
267  if (m_startingTimecodeOffset == -1ms)
268  m_startingTimecodeOffset = tc - 1ms;
270 
271  pkt->pts = tc.count() * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000;
272  pkt->dts = AV_NOPTS_VALUE;
273  pkt->stream_index= m_videoStream->index;
274 
275  ret = av_interleaved_write_frame(m_ctx, pkt);
276  if (ret != 0)
277  LOG(VB_RECORD, LOG_ERR, LOC + "WriteVideoFrame(): av_interleaved_write_frame couldn't write Video");
278 
279  Frame->m_timecode = tc + m_startingTimecodeOffset;
280  m_framesWritten++;
281  av_packet_unref(pkt);
282  av_packet_free(&pkt);
283  return 1;
284 }
285 
286 int MythAVFormatWriter::WriteAudioFrame(unsigned char *Buffer, int /*FrameNumber*/, std::chrono::milliseconds &Timecode)
287 {
288 #if (Q_BYTE_ORDER == Q_BIG_ENDIAN)
289  auto buf16 = reinterpret_cast<uint16_t *>(Buffer);
290  for (int i = 0; i < m_audioChannels * m_audioFrameSize; i++)
291  buf16[i] = qFromLittleEndian<quint16>(buf16[i]);
292 #endif
293 
294  AVCodecContext *avctx = m_codecMap.GetCodecContext(m_audioStream);
295  int samples_per_avframe = m_audioFrameSize * m_audioChannels;
296  int sampleSizeIn = AudioOutputSettings::SampleSize(FORMAT_S16);
297  AudioFormat format = AudioOutputSettings::AVSampleFormatToFormat(avctx->sample_fmt);
298  int sampleSizeOut = AudioOutputSettings::SampleSize(format);
299 
300  AVPacket *pkt = av_packet_alloc();
301  if (pkt == nullptr)
302  {
303  LOG(VB_RECORD, LOG_ERR, "packet allocation failed");
304  return AVERROR(ENOMEM);
305  }
306 
307  if (av_get_packed_sample_fmt(avctx->sample_fmt) == AV_SAMPLE_FMT_FLT)
308  {
309  AudioOutputUtil::toFloat(FORMAT_S16, static_cast<void*>(m_audioInBuf),
310  static_cast<void*>(Buffer), samples_per_avframe * sampleSizeIn);
312  }
313  if (av_sample_fmt_is_planar(avctx->sample_fmt))
314  {
317  samples_per_avframe * sampleSizeOut);
318 
319  // init AVFrame for planar data (input is interleaved)
320  for (int j = 0, jj = 0; j < m_audioChannels; j++, jj += m_audioFrameSize)
321  m_audPicture->data[j] = m_audioInPBuf + static_cast<ptrdiff_t>(jj) * sampleSizeOut;
322  }
323  else
324  {
325  m_audPicture->data[0] = Buffer;
326  }
327 
328  m_audPicture->linesize[0] = m_audioFrameSize;
329  m_audPicture->nb_samples = m_audioFrameSize;
330  m_audPicture->format = avctx->sample_fmt;
331  m_audPicture->extended_data = m_audPicture->data;
332  m_bufferedAudioFrameTimes.push_back(Timecode);
333 
334  // SUGGESTION
335  // Now that avcodec_encode_audio2 is deprecated and replaced
336  // by 2 calls, this could be optimized
337  // into separate routines or separate threads.
338  bool got_packet = false;
339  int ret = avcodec_receive_packet(avctx, pkt);
340  if (ret == 0)
341  got_packet = true;
342  if (ret == AVERROR(EAGAIN))
343  ret = 0;
344  if (ret == 0)
345  ret = avcodec_send_frame(avctx, m_audPicture);
346  // if ret from avcodec_send_frame is AVERROR(EAGAIN) then
347  // there are 2 packets to be received while only 1 frame to be
348  // sent. The code does not cater for this. Hopefully it will not happen.
349 
350  if (ret < 0)
351  {
352  std::string error;
353  LOG(VB_GENERAL, LOG_ERR, LOC + QString("audio encode error: %1 (%2)")
354  .arg(av_make_error_stdstring(error, ret)).arg(got_packet));
355  av_packet_free(&pkt);
356  return ret;
357  }
358 
359  if (!got_packet)
360  {
361  av_packet_free(&pkt);
362  return ret;
363  }
364 
365  std::chrono::milliseconds tc = Timecode;
366 
367  if (!m_bufferedAudioFrameTimes.empty())
368  tc = m_bufferedAudioFrameTimes.takeFirst();
369 
370  if (m_startingTimecodeOffset == -1ms)
371  m_startingTimecodeOffset = tc - 1ms;
373 
374  if (m_avVideoCodec)
375  pkt->pts = tc.count() * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000;
376  else
377  pkt->pts = tc.count() * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000;
378 
379  pkt->dts = AV_NOPTS_VALUE;
380  pkt->flags |= AV_PKT_FLAG_KEY;
381  pkt->stream_index = m_audioStream->index;
382 
383  ret = av_interleaved_write_frame(m_ctx, pkt);
384  if (ret != 0)
385  LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): av_interleaved_write_frame couldn't write Audio");
386 
387  Timecode = tc + m_startingTimecodeOffset;
388  av_packet_unref(pkt);
389  av_packet_free(&pkt);
390  return 1;
391 }
392 
393 int MythAVFormatWriter::WriteTextFrame(int /*VBIMode*/, unsigned char* /*Buffer*/, int /*Length*/,
394  std::chrono::milliseconds /*Timecode*/, int /*PageNumber*/)
395 {
396  return 1;
397 }
398 
400 {
401  return 1;
402 }
403 
405 {
406  return false;
407 }
408 
409 bool MythAVFormatWriter::ReOpen(const QString& Filename)
410 {
411  bool result = m_buffer->ReOpen(Filename);
412  if (result)
413  m_filename = Filename;
414  return result;
415 }
416 
418 {
419  AVStream *stream = avformat_new_stream(m_ctx, nullptr);
420  if (!stream)
421  {
422  LOG(VB_RECORD, LOG_ERR, LOC + "AddVideoStream(): avformat_new_stream() failed");
423  return nullptr;
424  }
425 
426  stream->id = 0;
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;
431 
432  const AVCodec *codec = avcodec_find_encoder(m_ctx->oformat->video_codec);
433  if (!codec)
434  {
435  LOG(VB_RECORD, LOG_ERR, LOC + "AddVideoStream(): avcodec_find_encoder() failed");
436  return nullptr;
437  }
438 
440  AVCodecContext *context = m_codecMap.GetCodecContext(stream, codec);
441  context->codec = codec;
442  context->codec_id = m_ctx->oformat->video_codec;
443  context->codec_type = AVMEDIA_TYPE_VIDEO;
444  context->bit_rate = m_videoBitrate;
445  context->width = m_width;
446  context->height = m_height;
447 
448  // c->sample_aspect_ratio.num = (int)floor(m_aspect * 10000);
449  // c->sample_aspect_ratio.den = 10000;
450 
451  context->time_base = GetCodecTimeBase();
452  context->gop_size = m_keyFrameDist;
453  context->pix_fmt = AV_PIX_FMT_YUV420P;
454  context->thread_count = m_encodingThreadCount;
455  context->thread_type = FF_THREAD_SLICE;
456 
457  if (context->codec_id == AV_CODEC_ID_MPEG2VIDEO)
458  {
459  context->max_b_frames = 2;
460  }
461  else if (context->codec_id == AV_CODEC_ID_MPEG1VIDEO)
462  {
463  context->mb_decision = 2;
464  }
465  else if (context->codec_id == AV_CODEC_ID_H264)
466  {
467 
468  // Try to provide the widest software/device support by automatically using
469  // the Baseline profile where the given bitrate and resolution permits
470 
471  if ((context->height > 720) || // Approximate highest resolution supported by Baseline 3.1
472  (context->bit_rate > 1400000)) // 14,000 Kbps aka 14Mbps maximum permissable rate for Baseline 3.1
473  {
474  context->level = 40;
475  // AVCodecContext AVOptions:
476  av_opt_set(context->priv_data, "profile", "main", 0);
477  }
478  else if ((context->height > 576) || // Approximate highest resolution supported by Baseline 3.0
479  (context->bit_rate > 1000000)) // 10,000 Kbps aka 10Mbps maximum permissable rate for Baseline 3.0
480  {
481  context->level = 31;
482  // AVCodecContext AVOptions:
483  av_opt_set(context->priv_data, "profile", "baseline", 0);
484  }
485  else
486  {
487  context->level = 30; // Baseline 3.0 is the most widely supported, but it's limited to SD
488  // AVCodecContext AVOptions:
489  av_opt_set(context->priv_data, "profile", "baseline", 0);
490  }
491 
492  // AVCodecContext AVOptions:
493  context->max_b_frames = 0;
494  context->slices = 8;
495  context->flags |= AV_CODEC_FLAG_LOOP_FILTER;
496  context->me_cmp |= 1;
497  // c->me_method = ME_HEX;
498  // av_opt_set_int(c, "me_method", ME_HEX, 0);
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;
503  // c->scenechange_threshold = 40;
504  av_opt_set_int(context, "sc_threshold", 40, 0);
505  context->i_quant_factor = 0.71F;
506  // c->b_frame_strategy = 1;
507  av_opt_set_int(context, "b_strategy", 1, 0);
508  context->qcompress = 0.6F;
509  context->qmin = 10;
510  context->qmax = 51;
511  context->max_qdiff = 4;
512  context->refs = 3;
513  context->trellis = 0;
514 
515  // libx264 AVOptions:
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);
523 
524  // libx264 AVOptions:
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);
527  }
528 
529  if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
530  context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
531 
532  return stream;
533 }
534 
536 {
537  if (!m_width || !m_height)
538  return false;
539 
540  AVCodecContext *context = m_codecMap.GetCodecContext(m_videoStream);
541  if (avcodec_open2(context, nullptr, nullptr) < 0)
542  {
543  LOG(VB_RECORD, LOG_ERR, LOC + "OpenVideo(): avcodec_open() failed");
544  return false;
545  }
546 
547  if (!m_picture)
548  {
549  m_picture = AllocPicture(context->pix_fmt);
550  if (!m_picture)
551  {
552  LOG(VB_RECORD, LOG_ERR, LOC + "OpenVideo(): AllocPicture() failed");
553  return false;
554  }
555  }
556  else
557  {
558  av_frame_unref(m_picture);
559  }
560 
561  return true;
562 }
563 
565 {
566  AVStream *stream = avformat_new_stream(m_ctx, nullptr);
567  if (!stream)
568  {
569  LOG(VB_RECORD, LOG_ERR, LOC + "AddAudioStream(): avformat_new_stream() failed");
570  return nullptr;
571  }
572  stream->id = 1;
573 
574  AVCodecContext *context = m_codecMap.GetCodecContext(stream, nullptr, true);
575 
576  context->codec_id = m_ctx->oformat->audio_codec;
577  context->codec_type = AVMEDIA_TYPE_AUDIO;
578  context->bit_rate = m_audioBitrate;
579  context->sample_rate = m_audioFrameRate;
580  av_channel_layout_default(&(context->ch_layout), m_audioChannels);
581 
582  // c->flags |= CODEC_FLAG_QSCALE; // VBR
583  // c->global_quality = blah;
584 
585  if (!m_avVideoCodec)
586  {
587  context->time_base = GetCodecTimeBase();
588  stream->time_base.den = 90000;
589  stream->time_base.num = 1;
590  }
591 
592  if (m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
593  context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
594 
595  return stream;
596 }
597 
598 bool MythAVFormatWriter::FindAudioFormat(AVCodecContext *Ctx, const AVCodec *Codec, AVSampleFormat Format)
599 {
600  if (Codec->sample_fmts)
601  {
602  for (int i = 0; Codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
603  {
604  if (av_get_packed_sample_fmt(Codec->sample_fmts[i]) == Format)
605  {
606  Ctx->sample_fmt = Codec->sample_fmts[i];
607  return true;
608  }
609  }
610  }
611  return false;
612 }
613 
615 {
616  AVCodecContext *context = m_codecMap.GetCodecContext(m_audioStream);
617  context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
618 
619  const AVCodec *codec = avcodec_find_encoder(context->codec_id);
620  if (!codec)
621  {
622  LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): avcodec_find_encoder() failed");
623  return false;
624  }
625 
626  // try to find suitable format we can use. avcodec_open2 will fail if we don't
627  // find one, so no need to worry otherwise. Can only handle S16 or FLOAT
628  // we give priority to S16 as libmp3lame requires aligned floats which we can't guarantee
629  if (!FindAudioFormat(context, codec, AV_SAMPLE_FMT_S16))
630  FindAudioFormat(context, codec, AV_SAMPLE_FMT_FLT);
631 
632  if (avcodec_open2(context, codec, nullptr) < 0)
633  {
634  LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): avcodec_open() failed");
635  return false;
636  }
637 
638  m_audioFrameSize = context->frame_size; // number of *samples* per channel in an AVFrame
639 
640  m_audPicture = av_frame_alloc();
641  if (!m_audPicture)
642  {
643  LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): alloc_frame() failed");
644  return false;
645  }
646 
647  auto size = static_cast<size_t>(m_audioFrameSize) * m_audioChannels *
648  av_get_bytes_per_sample(context->sample_fmt);
649  if (av_get_packed_sample_fmt(context->sample_fmt) == AV_SAMPLE_FMT_FLT)
650  {
651  // allocate buffer to convert from S16 to float
652  if (!(m_audioInBuf = static_cast<unsigned char*>(av_malloc(size))))
653  return false;
654  }
655 
656  if (av_sample_fmt_is_planar(context->sample_fmt))
657  {
658  // allocate buffer to convert interleaved to planar audio
659  if (!(m_audioInPBuf = static_cast<unsigned char*>(av_malloc(size))))
660  return false;
661  }
662  return true;
663 }
664 
665 AVFrame* MythAVFormatWriter::AllocPicture(enum AVPixelFormat PixFmt)
666 {
667  AVFrame *picture = av_frame_alloc();
668  if (!picture)
669  {
670  LOG(VB_RECORD, LOG_ERR, LOC + "AllocPicture failed");
671  return nullptr;
672  }
673 
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)));
676  if (!buffer)
677  {
678  LOG(VB_RECORD, LOG_ERR, LOC + "AllocPicture(): av_malloc() failed");
679  av_frame_free(&picture);
680  return nullptr;
681  }
682 
683  av_image_fill_arrays(picture->data, picture->linesize, buffer, PixFmt, m_width, m_height, IMAGE_ALIGN);
684  return picture;
685 }
686 
688 {
689  AVRational result;
690  result.den = static_cast<int>(floor(m_frameRate * 100));
691  result.num = 100;
692 
693  if (m_avVideoCodec && m_avVideoCodec->supported_framerates)
694  {
695  const AVRational *rates = m_avVideoCodec->supported_framerates;
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++)
700  {
701  AVRational error = av_sub_q(req, *rates);
702  if (error.num < 0)
703  error.num *= -1;
704  if (av_cmp_q(error, best_error) < 0)
705  {
706  best_error = error;
707  best = rates;
708  }
709  }
710 
711  if (best && best->num && best->den)
712  {
713  result.den = best->num;
714  result.num = best->den;
715  }
716  }
717 
718  if (result.den == 2997)
719  {
720  result.den = 30000;
721  result.num = 1001;
722  }
723  else if (result.den == 5994)
724  {
725  result.den = 60000;
726  result.num = 1001;
727  }
728 
729  return result;
730 }
MythMediaWriter::m_audioChannels
int m_audioChannels
Definition: mythmediawriter.h:62
MythMediaWriter::m_audioBitrate
int m_audioBitrate
Definition: mythmediawriter.h:61
MythAVFormatWriter::m_fmt
AVOutputFormat m_fmt
Definition: mythavformatwriter.h:50
AudioOutputSettings::AVSampleFormatToFormat
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
Definition: audiooutputsettings.cpp:198
MythMediaWriter::m_videoCodec
QString m_videoCodec
Definition: mythmediawriter.h:53
MythAVFormatWriter::OpenVideo
bool OpenVideo(void)
Definition: mythavformatwriter.cpp:535
error
static void error(const char *str,...)
Definition: vbi.cpp:36
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:27
MythCodecMap::GetCodecContext
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
Definition: mythavutil.cpp:287
MythAVFormatWriter::GetCodecTimeBase
AVRational GetCodecTimeBase(void)
Definition: mythavformatwriter.cpp:687
MythAVFormatWriter::ReOpen
bool ReOpen(const QString &Filename)
Definition: mythavformatwriter.cpp:409
MythAVFormatWriter::~MythAVFormatWriter
~MythAVFormatWriter() override
Definition: mythavformatwriter.cpp:45
audiooutpututil.h
MythAVFormatWriter::m_avfBuffer
MythAVFormatBuffer * m_avfBuffer
Definition: mythavformatwriter.h:48
MythMediaBuffer::ReOpen
virtual bool ReOpen(const QString &="")
Definition: mythmediabuffer.h:136
MythAVFormatWriter::WriteSeekTable
int WriteSeekTable(void) override
Definition: mythavformatwriter.cpp:399
AudioOutputUtil::toFloat
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
Definition: audiooutpututil.cpp:72
MythAVFormatWriter::SwitchToNextFile
bool SwitchToNextFile(void) override
Definition: mythavformatwriter.cpp:404
Frame
Definition: zmdefines.h:93
MythMediaWriter::m_container
QString m_container
Definition: mythmediawriter.h:52
MythMediaWriter::m_height
int m_height
Definition: mythmediawriter.h:56
AudioOutputSettings::SampleSize
static int SampleSize(AudioFormat format)
Definition: audiooutputsettings.cpp:180
MythAVFormatWriter::AddVideoStream
AVStream * AddVideoStream(void)
Definition: mythavformatwriter.cpp:417
MythMediaWriter::m_videoBitrate
int m_videoBitrate
Definition: mythmediawriter.h:54
MythDate::Format
Format
Definition: mythdate.h:15
MythMediaWriter::m_keyFrameDist
int m_keyFrameDist
Definition: mythmediawriter.h:59
MythAVFormatWriter::m_ctx
AVFormatContext * m_ctx
Definition: mythavformatwriter.h:51
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMediaWriter::m_audioFrameSize
int m_audioFrameSize
Definition: mythmediawriter.h:65
MythMediaWriter::m_encodingThreadCount
int m_encodingThreadCount
Definition: mythmediawriter.h:66
MythAVFormatWriter::m_audioStream
AVStream * m_audioStream
Definition: mythavformatwriter.h:55
MythAVFormatWriter::m_videoStream
AVStream * m_videoStream
Definition: mythavformatwriter.h:53
MythAVFormatWriter::m_codecMap
MythCodecMap m_codecMap
Definition: mythavformatwriter.h:52
MythAVFormatWriter::m_bufferedVideoFrameTypes
QList< int > m_bufferedVideoFrameTypes
Definition: mythavformatwriter.h:62
MythAVFormatWriter::m_buffer
MythMediaBuffer * m_buffer
Definition: mythavformatwriter.h:49
MythMediaWriter::m_audioCodec
QString m_audioCodec
Definition: mythmediawriter.h:60
MythMediaWriter::m_startingTimecodeOffset
std::chrono::milliseconds m_startingTimecodeOffset
Definition: mythmediawriter.h:68
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
LOC
#define LOC
Definition: mythavformatwriter.cpp:41
mythlogging.h
MythAVFormatWriter::OpenFile
bool OpenFile(void) override
Definition: mythavformatwriter.cpp:139
MythMediaWriter::m_encodingPreset
QString m_encodingPreset
Definition: mythmediawriter.h:69
MythAVFormatWriter::NextFrameIsKeyFrame
bool NextFrameIsKeyFrame(void)
Definition: mythavformatwriter.cpp:197
MythAVFormatWriter::FindAudioFormat
static bool FindAudioFormat(AVCodecContext *Ctx, const AVCodec *Codec, AVSampleFormat Format)
Definition: mythavformatwriter.cpp:598
MythAVFormatWriter::m_picture
AVFrame * m_picture
Definition: mythavformatwriter.h:57
MythCodecMap::FreeCodecContext
void FreeCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:335
MythAVFormatWriter::m_audioInPBuf
unsigned char * m_audioInPBuf
Definition: mythavformatwriter.h:60
MythMediaWriter::m_audioFrameRate
int m_audioFrameRate
Definition: mythmediawriter.h:63
MythAVFormatBuffer::GetURLProtocol
static URLProtocol * GetURLProtocol(void)
Definition: mythavformatbuffer.cpp:96
MythAVFormatWriter::CloseFile
bool CloseFile(void) override
Definition: mythavformatwriter.cpp:184
MythAVFormatWriter::OpenAudio
bool OpenAudio(void)
Definition: mythavformatwriter.cpp:614
mythavformatwriter.h
uint
unsigned int uint
Definition: compat.h:79
MythAVFormatWriter::WriteVideoFrame
int WriteVideoFrame(MythVideoFrame *Frame) override
Definition: mythavformatwriter.cpp:203
MythAVFormatWriter::m_audioInBuf
unsigned char * m_audioInBuf
Definition: mythavformatwriter.h:59
MythAVFormatWriter::m_avAudioCodec
const AVCodec * m_avAudioCodec
Definition: mythavformatwriter.h:56
Buffer
Definition: MythExternControl.h:36
MythAVFormatWriter::m_bufferedVideoFrameTimes
QList< std::chrono::milliseconds > m_bufferedVideoFrameTimes
Definition: mythavformatwriter.h:61
MythMediaWriter::m_encodingTune
QString m_encodingTune
Definition: mythmediawriter.h:70
mythcorecontext.h
MythMediaWriter::m_width
int m_width
Definition: mythmediawriter.h:55
mythavutil.h
MythAVFormatWriter::m_bufferedAudioFrameTimes
QList< std::chrono::milliseconds > m_bufferedAudioFrameTimes
Definition: mythavformatwriter.h:63
MythAVFormatWriter::m_avVideoCodec
const AVCodec * m_avVideoCodec
Definition: mythavformatwriter.h:54
MythAVFormatWriter::Cleanup
void Cleanup(void)
Definition: mythavformatwriter.cpp:174
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, std::chrono::milliseconds Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:98
MythMediaBuffer::GetLastError
QString GetLastError(void) const
Definition: mythmediabuffer.cpp:1761
MythAVFormatWriter::AddAudioStream
AVStream * AddAudioStream(void)
Definition: mythavformatwriter.cpp:564
MythAVFormatWriter::AllocPicture
AVFrame * AllocPicture(enum AVPixelFormat PixFmt)
Definition: mythavformatwriter.cpp:665
MythAVFormatWriter::m_audPicture
AVFrame * m_audPicture
Definition: mythavformatwriter.h:58
AudioOutputUtil::DeinterleaveSamples
static void DeinterleaveSamples(AudioFormat format, int channels, uint8_t *output, const uint8_t *input, int data_size)
Deinterleave input samples Deinterleave audio samples and compact them.
Definition: audiooutpututil.cpp:308
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
MythMediaWriter::m_filename
QString m_filename
Definition: mythmediawriter.h:51
MythVideoFrame
Definition: mythframe.h:88
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:24
MythAVFormatBuffer
Definition: mythavformatbuffer.h:13
build_compdb.filename
filename
Definition: build_compdb.py:21
MythMediaWriter::m_framesWritten
long long m_framesWritten
Definition: mythmediawriter.h:67
MythAVUtil::FillAVFrame
static int FillAVFrame(AVFrame *Frame, const MythVideoFrame *From, AVPixelFormat Fmt=AV_PIX_FMT_NONE)
Initialise AVFrame with content from MythVideoFrame.
Definition: mythavutil.cpp:198
MythAVFormatWriter::Init
bool Init(void) override
Definition: mythavformatwriter.cpp:64
av_make_error_stdstring
char * av_make_error_stdstring(std::string &errbuf, int errnum)
Definition: mythaverror.cpp:41
MythAVFormatWriter::WriteTextFrame
int WriteTextFrame(int VBIMode, unsigned char *Buffer, int Length, std::chrono::milliseconds Timecode, int PageNumber) override
Definition: mythavformatwriter.cpp:393
MythAVFormatWriter::WriteAudioFrame
int WriteAudioFrame(unsigned char *Buffer, int FrameNumber, std::chrono::milliseconds &Timecode) override
Definition: mythavformatwriter.cpp:286
MythMediaWriter::m_frameRate
double m_frameRate
Definition: mythmediawriter.h:58