MythTV  master
avformatwriter.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  *
3  * Class AVFormatWriter
4  *
5  * Copyright (C) Chris Pinkham 2011
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "mythlogging.h"
23 #include "mythcorecontext.h"
24 #include "avformatwriter.h"
25 #include "audiooutpututil.h"
26 #include "mythavutil.h"
27 
28 extern "C" {
29 #if HAVE_BIGENDIAN
30 #include "bswap.h"
31 #endif
32 #include "libavutil/opt.h"
33 #include "libavutil/samplefmt.h"
34 #include "libavutil/imgutils.h"
35 }
36 
37 #define LOC QString("AVFW(%1): ").arg(m_filename)
38 #define LOC_ERR QString("AVFW(%1) Error: ").arg(m_filename)
39 #define LOC_WARN QString("AVFW(%1) Warning: ").arg(m_filename)
40 
42 {
43  QMutexLocker locker(avcodeclock);
44 
45  if (m_ctx)
46  {
47  (void)av_write_trailer(m_ctx);
48  avio_closep(&m_ctx->pb);
49  for(unsigned int i = 0; i < m_ctx->nb_streams; i++) {
50  av_freep(&m_ctx->streams[i]);
51  }
52  av_freep(&m_ctx);
53  }
54 
55  if (m_audioInBuf)
56  av_freep(&m_audioInBuf);
57 
58  if (m_audioInPBuf)
59  av_freep(&m_audioInPBuf);
60 
61  if (m_audPicture)
62  av_frame_free(&m_audPicture);
63 
64  Cleanup();
65 
66  av_frame_free(&m_picture);
67 }
68 
70 {
71  AVOutputFormat *fmt = av_guess_format(m_container.toLatin1().constData(),
72  nullptr, nullptr);
73  if (!fmt)
74  {
75  LOG(VB_RECORD, LOG_ERR, LOC +
76  QString("Init(): Unable to guess AVOutputFormat from container %1")
77  .arg(m_container));
78  return false;
79  }
80 
81  m_fmt = *fmt;
82 
83  if (m_width && m_height)
84  {
85  m_avVideoCodec = avcodec_find_encoder_by_name(
86  m_videoCodec.toLatin1().constData());
87  if (!m_avVideoCodec)
88  {
89  LOG(VB_RECORD, LOG_ERR, LOC +
90  QString("Init(): Unable to find video codec %1").arg(m_videoCodec));
91  return false;
92  }
93 
94  m_fmt.video_codec = m_avVideoCodec->id;
95  }
96  else
97  m_fmt.video_codec = AV_CODEC_ID_NONE;
98 
99  m_avAudioCodec = avcodec_find_encoder_by_name(
100  m_audioCodec.toLatin1().constData());
101  if (!m_avAudioCodec)
102  {
103  LOG(VB_RECORD, LOG_ERR, LOC +
104  QString("Init(): Unable to find audio codec %1").arg(m_audioCodec));
105  return false;
106  }
107 
108  m_fmt.audio_codec = m_avAudioCodec->id;
109 
110  m_ctx = avformat_alloc_context();
111  if (!m_ctx)
112  {
113  LOG(VB_RECORD, LOG_ERR,
114  LOC + "Init(): Unable to allocate AVFormatContext");
115  return false;
116  }
117 
118  m_ctx->oformat = &m_fmt;
119 
120  if (m_container == "mpegts")
121  m_ctx->packet_size = 2324;
122 
123  snprintf(m_ctx->filename, sizeof(m_ctx->filename), "%s",
124  m_filename.toLatin1().constData());
125 
126  if (m_fmt.video_codec != AV_CODEC_ID_NONE)
128  if (m_fmt.audio_codec != AV_CODEC_ID_NONE)
130 
131  if ((m_videoStream) && (!OpenVideo()))
132  {
133  LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenVideo() failed");
134  return false;
135  }
136 
137  if ((m_audioStream) && (!OpenAudio()))
138  {
139  LOG(VB_RECORD, LOG_ERR, LOC + "Init(): OpenAudio() failed");
140  return false;
141  }
142 
143  return true;
144 }
145 
147 {
148  if (!(m_fmt.flags & AVFMT_NOFILE))
149  {
150  if (avio_open(&m_ctx->pb, m_filename.toLatin1().constData(),
151  AVIO_FLAG_WRITE) < 0)
152  {
153  LOG(VB_RECORD, LOG_ERR, LOC + "OpenFile(): avio_open() failed");
154  return false;
155  }
156  }
157 
159 
160  if (!m_ringBuffer || !m_ringBuffer->GetLastError().isEmpty())
161  {
162  LOG(VB_RECORD, LOG_ERR, LOC +
163  QString("OpenFile(): RingBuffer::Create() failed: '%1'")
164  .arg(m_ringBuffer ? m_ringBuffer->GetLastError() : ""));
165  Cleanup();
166  return false;
167  }
168 
170  URLContext *uc = (URLContext *)m_ctx->pb->opaque;
172  uc->priv_data = (void *)m_avfRingBuffer;
173 
174  if (avformat_write_header(m_ctx, nullptr) < 0)
175  {
176  Cleanup();
177  return false;
178  }
179 
180  return true;
181 }
182 
184 {
185  if (m_ctx && m_ctx->pb)
186  {
187  avio_closep(&m_ctx->pb);
188  }
189  delete m_avfRingBuffer;
190  m_avfRingBuffer = nullptr;
191  delete m_ringBuffer;
192  m_ringBuffer = nullptr;
193 }
194 
196 {
197  if (m_ctx)
198  {
199  (void)av_write_trailer(m_ctx);
200  avio_close(m_ctx->pb);
201  for(unsigned int i = 0; i < m_ctx->nb_streams; i++) {
202  av_freep(&m_ctx->streams[i]);
203  }
204 
205  av_freep(&m_ctx);
206  }
207 
208  return true;
209 }
210 
212 {
213  return (m_bufferedVideoFrameTypes.isEmpty()) ||
214  (m_bufferedVideoFrameTypes.first() == AV_PICTURE_TYPE_I);
215 }
216 
218 {
219  int framesEncoded = m_framesWritten + m_bufferedVideoFrameTimes.size();
220 
221  av_frame_unref(m_picture);
222  AVPictureFill(m_picture, frame);
223  m_picture->pts = framesEncoded + 1;
224 
225  if ((framesEncoded % m_keyFrameDist) == 0)
226  m_picture->pict_type = AV_PICTURE_TYPE_I;
227  else
228  m_picture->pict_type = AV_PICTURE_TYPE_NONE;
229 
230  int got_pkt = 0;
231  int ret = 0;
232 
233  m_bufferedVideoFrameTimes.push_back(frame->timecode);
234  m_bufferedVideoFrameTypes.push_back(m_picture->pict_type);
235 
236  AVPacket pkt;
237  av_init_packet(&pkt);
238  pkt.data = nullptr;
239  pkt.size = 0;
240  AVCodecContext *avctx = gCodecMap->getCodecContext(m_videoStream);
241  {
242  QMutexLocker locker(avcodeclock);
243  ret = avcodec_encode_video2(avctx, &pkt,
244  m_picture, &got_pkt);
245  }
246 
247  if (ret < 0)
248  {
249  LOG(VB_RECORD, LOG_ERR, "avcodec_encode_video2() failed");
250  return ret;
251  }
252 
253  if (!got_pkt)
254  {
255  //LOG(VB_RECORD, LOG_DEBUG, QString("WriteVideoFrame(): Frame Buffered: cs: %1, mfw: %2, f->tc: %3, fn: %4, pt: %5").arg(pkt.size).arg(m_framesWritten).arg(frame->timecode).arg(frame->frameNumber).arg(m_picture->pict_type));
256  return ret;
257  }
258 
259  long long tc = frame->timecode;
260 
261  if (!m_bufferedVideoFrameTimes.isEmpty())
262  tc = m_bufferedVideoFrameTimes.takeFirst();
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 == -1)
271  m_startingTimecodeOffset = tc - 1;
273 
274  pkt.pts = tc * 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  //LOG(VB_RECORD, LOG_DEBUG, QString("WriteVideoFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, pic->pts: %6, f->tc: %7, pt: %8").arg(pkt.size).arg(m_framesWritten).arg(pkt.pts).arg(tc).arg(frame->frameNumber).arg(m_picture->pts).arg(frame->timecode).arg(m_picture->pict_type));
279  ret = av_interleaved_write_frame(m_ctx, &pkt);
280  if (ret != 0)
281  LOG(VB_RECORD, LOG_ERR, LOC + "WriteVideoFrame(): "
282  "av_interleaved_write_frame couldn't write Video");
283 
284  frame->timecode = tc + m_startingTimecodeOffset;
285  m_framesWritten++;
286 
287  av_packet_unref(&pkt);
288 
289  return 1;
290 }
291 
292 #if HAVE_BIGENDIAN
293 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels)
294  __attribute__ ((unused)); /* <- suppress compiler warning */
295 
296 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels)
297 {
298  for (int i = 0; i < audio_channels * buf_cnt; i++)
299  buf[i] = bswap_16(buf[i]);
300 }
301 #endif
302 
303 int AVFormatWriter::WriteAudioFrame(unsigned char *buf, int /*fnum*/, long long &timecode)
304 {
305 #if HAVE_BIGENDIAN
306  bswap_16_buf((short int*) buf, m_audioFrameSize, m_audioChannels);
307 #endif
308 
309  bool got_packet = false;
310  int ret = 0;
311  AVCodecContext *avctx = gCodecMap->getCodecContext(m_audioStream);
312  int samples_per_avframe = m_audioFrameSize * m_audioChannels;
313  int sampleSizeIn = AudioOutputSettings::SampleSize(FORMAT_S16);
314  AudioFormat format =
316  int sampleSizeOut = AudioOutputSettings::SampleSize(format);
317 
318  AVPacket pkt;
319  av_init_packet(&pkt);
320  pkt.data = nullptr;
321  pkt.size = 0;
322 
323  if (av_get_packed_sample_fmt(avctx->sample_fmt) == AV_SAMPLE_FMT_FLT)
324  {
325  AudioOutputUtil::toFloat(FORMAT_S16, (void *)m_audioInBuf, (void *)buf,
326  samples_per_avframe * sampleSizeIn);
327  buf = m_audioInBuf;
328  }
329  if (av_sample_fmt_is_planar(avctx->sample_fmt))
330  {
334  buf,
335  samples_per_avframe * sampleSizeOut);
336 
337  // init AVFrame for planar data (input is interleaved)
338  for (int j = 0, jj = 0; j < m_audioChannels; j++, jj += m_audioFrameSize)
339  {
340  m_audPicture->data[j] = m_audioInPBuf + jj * sampleSizeOut;
341  }
342  }
343  else
344  {
345  m_audPicture->data[0] = buf;
346  }
347 
348  m_audPicture->linesize[0] = m_audioFrameSize;
349  m_audPicture->nb_samples = m_audioFrameSize;
350  m_audPicture->format = avctx->sample_fmt;
351  m_audPicture->extended_data = m_audPicture->data;
352 
353  m_bufferedAudioFrameTimes.push_back(timecode);
354 
355  {
356  QMutexLocker locker(avcodeclock);
357  // SUGGESTION
358  // Now that avcodec_encode_audio2 is deprecated and replaced
359  // by 2 calls, this could be optimized
360  // into separate routines or separate threads.
361  got_packet = false;
362  ret = avcodec_receive_packet(avctx, &pkt);
363  if (ret == 0)
364  got_packet = true;
365  if (ret == AVERROR(EAGAIN))
366  ret = 0;
367  if (ret == 0)
368  ret = avcodec_send_frame(avctx, m_audPicture);
369  // if ret from avcodec_send_frame is AVERROR(EAGAIN) then
370  // there are 2 packets to be received while only 1 frame to be
371  // sent. The code does not cater for this. Hopefully it will not happen.
372  }
373 
374  if (ret < 0)
375  {
376  char error[AV_ERROR_MAX_STRING_SIZE];
377  LOG(VB_GENERAL, LOG_ERR, LOC +
378  QString("audio encode error: %1 (%2)")
379  .arg(av_make_error_string(error, sizeof(error), ret))
380  .arg(got_packet));
381  return ret;
382  }
383 
384  if (!got_packet)
385  {
386  //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): Frame Buffered: cs: %1, mfw: %2, f->tc: %3, fn: %4").arg(m_audPkt->size).arg(m_framesWritten).arg(timecode).arg(fnum));
387  return ret;
388  }
389 
390  long long tc = timecode;
391 
392  if (!m_bufferedAudioFrameTimes.empty())
393  tc = m_bufferedAudioFrameTimes.takeFirst();
394 
395  if (m_startingTimecodeOffset == -1)
396  m_startingTimecodeOffset = tc - 1;
398 
399  if (m_avVideoCodec)
400  pkt.pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000;
401  else
402  pkt.pts = tc * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000;
403 
404  pkt.dts = AV_NOPTS_VALUE;
405  pkt.flags |= AV_PKT_FLAG_KEY;
406  pkt.stream_index = m_audioStream->index;
407 
408  //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, f->tc: %6").arg(m_audPkt->size).arg(m_framesWritten).arg(m_audPkt->pts).arg(tc).arg(fnum).arg(timecode));
409 
410  ret = av_interleaved_write_frame(m_ctx, &pkt);
411  if (ret != 0)
412  LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): "
413  "av_interleaved_write_frame couldn't write Audio");
414  timecode = tc + m_startingTimecodeOffset;
415 
416  av_packet_unref(&pkt);
417 
418  return 1;
419 }
420 
421 int AVFormatWriter::WriteTextFrame(int /*vbimode*/, unsigned char */*buf*/, int /*len*/,
422  long long /*timecode*/, int /*pagenr*/)
423 {
424  return 1;
425 }
426 
427 bool AVFormatWriter::ReOpen(const QString& filename)
428 {
429  bool result = m_ringBuffer->ReOpen(filename);
430 
431  if (result)
432  m_filename = filename;
433 
434  return result;
435 }
436 
438 {
439  AVCodecContext *c;
440  AVStream *st;
441  AVCodec *codec;
442 
443  st = avformat_new_stream(m_ctx, nullptr);
444  if (!st)
445  {
446  LOG(VB_RECORD, LOG_ERR,
447  LOC + "AddVideoStream(): avformat_new_stream() failed");
448  return nullptr;
449  }
450  st->id = 0;
451 
452 
453  codec = avcodec_find_encoder(m_ctx->oformat->video_codec);
454  if (!codec)
455  {
456  LOG(VB_RECORD, LOG_ERR,
457  LOC + "AddVideoStream(): avcodec_find_encoder() failed");
458  return nullptr;
459  }
460 
462  c = gCodecMap->getCodecContext(st, codec);
463 
464  c->codec = codec;
465  c->codec_id = m_ctx->oformat->video_codec;
466  c->codec_type = AVMEDIA_TYPE_VIDEO;
467 
468  c->bit_rate = m_videoBitrate;
469  c->width = m_width;
470  c->height = m_height;
471 
472  // c->sample_aspect_ratio.num = (int)floor(m_aspect * 10000);
473  // c->sample_aspect_ratio.den = 10000;
474 
475  c->time_base = GetCodecTimeBase();
476 
477  st->time_base.den = 90000;
478  st->time_base.num = 1;
479  st->r_frame_rate.num = 0;
480  st->r_frame_rate.den = 0;
481 
482  c->gop_size = m_keyFrameDist;
483  c->pix_fmt = AV_PIX_FMT_YUV420P;
484  c->thread_count = m_encodingThreadCount;
485  c->thread_type = FF_THREAD_SLICE;
486 
487  if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
488  c->max_b_frames = 2;
489  }
490  else if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
491  {
492  c->mb_decision = 2;
493  }
494  else if (c->codec_id == AV_CODEC_ID_H264)
495  {
496 
497  // Try to provide the widest software/device support by automatically using
498  // the Baseline profile where the given bitrate and resolution permits
499 
500  if ((c->height > 720) || // Approximate highest resolution supported by Baseline 3.1
501  (c->bit_rate > 1000000)) // 14,000 Kbps aka 14Mbps maximum permissable rate for Baseline 3.1
502  {
503  c->level = 40;
504  // AVCodecContext AVOptions:
505  av_opt_set(c->priv_data, "profile", "main", 0);
506  }
507  else if ((c->height > 576) || // Approximate highest resolution supported by Baseline 3.0
508  (c->bit_rate > 1000000)) // 10,000 Kbps aka 10Mbps maximum permissable rate for Baseline 3.0
509  {
510  c->level = 31;
511  // AVCodecContext AVOptions:
512  av_opt_set(c->priv_data, "profile", "baseline", 0);
513  }
514  else
515  {
516  c->level = 30; // Baseline 3.0 is the most widely supported, but it's limited to SD
517  // AVCodecContext AVOptions:
518  av_opt_set(c->priv_data, "profile", "baseline", 0);
519  }
520 
521  // AVCodecContext AVOptions:
522  // c->coder_type = 0;
523  av_opt_set_int(c, "coder", FF_CODER_TYPE_VLC, 0);
524  c->max_b_frames = 0;
525  c->slices = 8;
526 
527  c->flags |= AV_CODEC_FLAG_LOOP_FILTER;
528  c->me_cmp |= 1;
529  // c->me_method = ME_HEX;
530  // av_opt_set_int(c, "me_method", ME_HEX, 0);
531  av_opt_set(c, "me_method", "hex", 0);
532  c->me_subpel_quality = 6;
533  c->me_range = 16;
534  c->keyint_min = 25;
535  // c->scenechange_threshold = 40;
536  av_opt_set_int(c, "sc_threshold", 40, 0);
537  c->i_quant_factor = 0.71;
538  // c->b_frame_strategy = 1;
539  av_opt_set_int(c, "b_strategy", 1, 0);
540  c->qcompress = 0.6;
541  c->qmin = 10;
542  c->qmax = 51;
543  c->max_qdiff = 4;
544  c->refs = 3;
545  c->trellis = 0;
546 
547  // libx264 AVOptions:
548  av_opt_set(c, "partitions", "i8x8,i4x4,p8x8,b8x8", 0);
549  av_opt_set_int(c, "direct-pred", 1, 0);
550  av_opt_set_int(c, "rc-lookahead", 0, 0);
551  av_opt_set_int(c, "fast-pskip", 1, 0);
552  av_opt_set_int(c, "mixed-refs", 1, 0);
553  av_opt_set_int(c, "8x8dct", 0, 0);
554  av_opt_set_int(c, "weightb", 0, 0);
555 
556  // libx264 AVOptions:
557  av_opt_set(c->priv_data, "preset",
558  m_encodingPreset.toLatin1().constData(), 0);
559  av_opt_set(c->priv_data, "tune",
560  m_encodingTune.toLatin1().constData(), 0);
561  }
562 
563  if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
564  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
565 
566  return st;
567 }
568 
570 {
571  AVCodecContext *c;
572 
574 
575  if (!m_width || !m_height)
576  return false;
577 
578  if (avcodec_open2(c, nullptr, nullptr) < 0)
579  {
580  LOG(VB_RECORD, LOG_ERR,
581  LOC + "OpenVideo(): avcodec_open() failed");
582  return false;
583  }
584 
585  if (!m_picture)
586  {
587  m_picture = AllocPicture(c->pix_fmt);
588  if (!m_picture)
589  {
590  LOG(VB_RECORD, LOG_ERR,
591  LOC + "OpenVideo(): AllocPicture() failed");
592  return false;
593  }
594  }
595  else
596  {
597  av_frame_unref(m_picture);
598  }
599 
600  return true;
601 }
602 
604 {
605  AVCodecContext *c;
606  AVStream *st;
607 
608  st = avformat_new_stream(m_ctx, nullptr);
609  if (!st)
610  {
611  LOG(VB_RECORD, LOG_ERR,
612  LOC + "AddAudioStream(): avformat_new_stream() failed");
613  return nullptr;
614  }
615  st->id = 1;
616 
617  c = gCodecMap->getCodecContext(st, nullptr, true);
618 
619  c->codec_id = m_ctx->oformat->audio_codec;
620  c->codec_type = AVMEDIA_TYPE_AUDIO;
621  c->bit_rate = m_audioBitrate;
622  c->sample_rate = m_audioFrameRate;
623  c->channels = m_audioChannels;
624 
625  // c->flags |= CODEC_FLAG_QSCALE; // VBR
626  // c->global_quality = blah;
627 
628  if (!m_avVideoCodec)
629  {
630  c->time_base = GetCodecTimeBase();
631  st->time_base.den = 90000;
632  st->time_base.num = 1;
633  }
634 
635  if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
636  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
637 
638  return st;
639 }
640 
641 bool AVFormatWriter::FindAudioFormat(AVCodecContext *ctx, AVCodec *c, AVSampleFormat format)
642 {
643  if (c->sample_fmts)
644  {
645  for (int i = 0; c->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
646  {
647  if (av_get_packed_sample_fmt(c->sample_fmts[i]) == format)
648  {
649  ctx->sample_fmt = c->sample_fmts[i];
650  return true;
651  }
652  }
653  }
654  return false;
655 }
656 
658 {
659  AVCodecContext *c;
660  AVCodec *codec;
661 
663 
664  c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
665 
666  codec = avcodec_find_encoder(c->codec_id);
667  if (!codec)
668  {
669  LOG(VB_RECORD, LOG_ERR,
670  LOC + "OpenAudio(): avcodec_find_encoder() failed");
671  return false;
672  }
673 
674  // try to find suitable format we can use. avcodec_open2 will fail if we don't
675  // find one, so no need to worry otherwise. Can only handle S16 or FLOAT
676  // we give priority to S16 as libmp3lame requires aligned floats which we can't guarantee
677  if (!FindAudioFormat(c, codec, AV_SAMPLE_FMT_S16))
678  {
679  FindAudioFormat(c, codec, AV_SAMPLE_FMT_FLT);
680  }
681 
682  if (avcodec_open2(c, codec, nullptr) < 0)
683  {
684  LOG(VB_RECORD, LOG_ERR,
685  LOC + "OpenAudio(): avcodec_open() failed");
686  return false;
687  }
688 
689  m_audioFrameSize = c->frame_size; // number of *samples* per channel in an AVFrame
690 
691  m_audPicture = av_frame_alloc();
692  if (!m_audPicture)
693  {
694  LOG(VB_RECORD, LOG_ERR,
695  LOC + "OpenAudio(): alloc_frame() failed");
696  return false;
697  }
698 
699  int samples_per_frame = m_audioFrameSize * m_audioChannels;
700  int bps = av_get_bytes_per_sample(c->sample_fmt);
701  if (av_get_packed_sample_fmt(c->sample_fmt) == AV_SAMPLE_FMT_FLT)
702  {
703  // allocate buffer to convert from S16 to float
704  if (!(m_audioInBuf = (unsigned char*)av_malloc(bps * samples_per_frame)))
705  return false;
706  }
707  if (av_sample_fmt_is_planar(c->sample_fmt))
708  {
709  // allocate buffer to convert interleaved to planar audio
710  if (!(m_audioInPBuf = (unsigned char*)av_malloc(bps * samples_per_frame)))
711  return false;
712  }
713  return true;
714 }
715 
716 AVFrame* AVFormatWriter::AllocPicture(enum AVPixelFormat pix_fmt)
717 {
718  AVFrame *picture;
719  unsigned char *picture_buf;
720  int size;
721 
722  picture = av_frame_alloc();
723  if (!picture)
724  {
725  LOG(VB_RECORD, LOG_ERR,
726  LOC + "AllocPicture(): avcodec_alloc_frame() failed");
727  return nullptr;
728  }
729  size = av_image_get_buffer_size(pix_fmt, m_width, m_height, IMAGE_ALIGN);
730  picture_buf = (unsigned char *)av_malloc(size);
731  if (!picture_buf)
732  {
733  LOG(VB_RECORD, LOG_ERR, LOC + "AllocPicture(): av_malloc() failed");
734  av_frame_free(&picture);
735  return nullptr;
736  }
737  av_image_fill_arrays(picture->data, picture->linesize,
738  picture_buf, pix_fmt, m_width, m_height, IMAGE_ALIGN);
739  return picture;
740 }
741 
743 {
744  AVRational result;
745 
746  result.den = (int)floor(m_frameRate * 100);
747  result.num = 100;
748 
749  if (m_avVideoCodec && m_avVideoCodec->supported_framerates) {
750  const AVRational *p= m_avVideoCodec->supported_framerates;
751  AVRational req = {result.den, result.num};
752  const AVRational *best = nullptr;
753  AVRational best_error= {INT_MAX, 1};
754  for(; p->den!=0; p++) {
755  AVRational error = av_sub_q(req, *p);
756  if (error.num <0)
757  error.num *= -1;
758  if (av_cmp_q(error, best_error) < 0) {
759  best_error = error;
760  best = p;
761  }
762  }
763 
764  if (best && best->num && best->den)
765  {
766  result.den = best->num;
767  result.num = best->den;
768  }
769  }
770 
771  if (result.den == 2997)
772  {
773  result.den = 30000;
774  result.num = 1001;
775  }
776  else if (result.den == 5994)
777  {
778  result.den = 60000;
779  result.num = 1001;
780  }
781 
782  return result;
783 }
784 
785 /* vim: set expandtab tabstop=4 shiftwidth=4: */
int WriteAudioFrame(unsigned char *buf, int fnum, long long &timecode) override
AVStream * m_audioStream
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
QString GetLastError(void) const
QString m_videoCodec
static void error(const char *str,...)
Definition: vbi.c:42
QString m_filename
struct AVFrame AVFrame
void freeCodecContext(const AVStream *)
Definition: mythavutil.cpp:430
bool ReOpen(const QString &filename)
bool Init(void) override
static RingBuffer * Create(const QString &xfilename, bool write, bool usereadahead=true, int timeout_ms=kDefaultOpenTimeout, bool stream_only=false)
Creates a RingBuffer instance.
Definition: ringbuffer.cpp:104
int WriteTextFrame(int vbimode, unsigned char *buf, int len, long long timecode, int pagenr) override
long long timecode
Definition: mythframe.h:49
bool FindAudioFormat(AVCodecContext *ctx, AVCodec *c, AVSampleFormat format)
AVCodec * m_avVideoCodec
long long m_startingTimecodeOffset
unsigned char * m_audioInBuf
AVFrame * AllocPicture(enum AVPixelFormat pix_fmt)
bool OpenAudio(void)
AVStream * AddVideoStream(void)
int AVPictureFill(AVFrame *pic, const VideoFrame *frame, AVPixelFormat fmt)
AVPictureFill Initialise AVFrame pic with content from VideoFrame frame.
Definition: mythavutil.cpp:65
QString m_container
bool CloseFile(void) override
MythCodecMap * gCodecMap
This global variable contains the MythCodecMap instance for the app.
Definition: mythavutil.cpp:380
QString m_encodingPreset
AVFRingBuffer * m_avfRingBuffer
QList< long long > m_bufferedVideoFrameTimes
static int SampleSize(AudioFormat format)
long long m_framesWritten
int WriteVideoFrame(VideoFrame *frame) override
QString m_audioCodec
RingBuffer * m_ringBuffer
AVCodecContext * getCodecContext(const AVStream *, const AVCodec *pCodec=nullptr, bool nullCodec=false)
Definition: mythavutil.cpp:391
void Cleanup(void)
void * av_malloc(unsigned int size)
AVRational GetCodecTimeBase(void)
AVFrame * m_audPicture
static URLProtocol * GetRingBufferURLProtocol(void)
QString m_encodingTune
AVCodec * m_avAudioCodec
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QMutex * avcodeclock
This global variable is used to makes certain calls to avlib threadsafe.
#define LOC
bool NextFrameIsKeyFrame(void)
unsigned char * m_audioInPBuf
AVStream * AddAudioStream(void)
bool OpenFile(void) override
QList< long long > m_bufferedAudioFrameTimes
QList< int > m_bufferedVideoFrameTypes
AVFormatContext * m_ctx
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
AVOutputFormat m_fmt
AVFrame * m_picture
bool OpenVideo(void)
virtual bool ReOpen(QString="")
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.
AVStream * m_videoStream