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