MythTV  master
spdifencoder.cpp
Go to the documentation of this file.
1 #include "config.h"
2 
3 #include "mythcorecontext.h"
4 
5 #include "compat.h"
6 #include "spdifencoder.h"
7 #include "mythlogging.h"
8 extern "C" {
9 #include "libavformat/avformat.h"
10 #include "libavutil/opt.h"
11 }
12 
13 #define LOC QString("SPDIFEncoder: ")
14 
24 SPDIFEncoder::SPDIFEncoder(const QString& muxer, AVCodecID codec_id)
25 {
26  memset(&m_buffer, 0, sizeof(m_buffer));
27 
28  QByteArray dev_ba = muxer.toLatin1();
29  AVOutputFormat *fmt;
30 
31  fmt = av_guess_format(dev_ba.constData(), nullptr, nullptr);
32  if (!fmt)
33  {
34  LOG(VB_AUDIO, LOG_ERR, LOC + "av_guess_format");
35  return;
36  }
37 
38  m_oc = avformat_alloc_context();
39  if (!m_oc)
40  {
41  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_alloc_context");
42  return;
43  }
44  m_oc->oformat = fmt;
45 
46  m_oc->pb = avio_alloc_context(m_buffer, sizeof(m_buffer), 1,
47  this, nullptr, funcIO, nullptr);
48  if (!m_oc->pb)
49  {
50  LOG(VB_AUDIO, LOG_ERR, LOC + "avio_alloc_context");
51  Destroy();
52  return;
53  }
54 
55  m_oc->pb->seekable = 0;
56  m_oc->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
57 
58  const AVCodec *codec = avcodec_find_decoder(codec_id);
59  if (!codec)
60  {
61  LOG(VB_AUDIO, LOG_ERR, LOC + "avcodec_find_decoder");
62  Destroy();
63  return;
64  }
65 
66  AVStream *stream = avformat_new_stream(m_oc, nullptr);
67  if (!stream)
68  {
69  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_new_stream");
70  Destroy();
71  return;
72  }
73 
74  stream->id = 1;
75  stream->codecpar->codec_id = codec->id;
76  stream->codecpar->codec_type = codec->type;
77  stream->codecpar->sample_rate = 48000; // dummy rate, so codecpar initialization doesn't fail.
78 
79  if (avformat_write_header(m_oc, nullptr) < 0)
80  {
81  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_write_header");
82  Destroy();
83  return;
84  }
85 
86  LOG(VB_AUDIO, LOG_INFO, LOC + QString("Creating %1 encoder (for %2)")
87  .arg(muxer).arg(ff_codec_id_string(codec_id)));
88 
89  m_complete = true;
90 }
91 
93 {
94  Destroy();
95 }
96 
102 void SPDIFEncoder::WriteFrame(unsigned char *data, int size)
103 {
104  AVPacket packet;
105  av_init_packet(&packet);
106  static int pts = 1; // to avoid warning "Encoder did not produce proper pts"
107  packet.pts = pts++;
108  packet.data = data;
109  packet.size = size;
110 
111  if (av_write_frame(m_oc, &packet) < 0)
112  {
113  LOG(VB_AUDIO, LOG_ERR, LOC + "av_write_frame");
114  }
115 }
116 
123 int SPDIFEncoder::GetData(unsigned char *buffer, int &dest_size)
124 {
125  if(m_size > 0)
126  {
127  memcpy(buffer, m_buffer, m_size);
128  dest_size = m_size;
129  m_size = 0;
130  return dest_size;
131  }
132  return -1;
133 }
134 
139 {
140  m_size = 0;
141 }
142 
150 {
151  if (!m_oc)
152  {
153  return false;
154  }
155  av_opt_set_int(m_oc->priv_data, "dtshd_rate", rate, 0);
156  return true;
157 }
158 
162 int SPDIFEncoder::funcIO(void *opaque, unsigned char *buf, int size)
163 {
164  SPDIFEncoder *enc = (SPDIFEncoder *)opaque;
165 
166  memcpy(enc->m_buffer + enc->m_size, buf, size);
167  enc->m_size += size;
168  return size;
169 }
170 
175 {
176  Reset();
177 
178  if (m_complete)
179  {
180  av_write_trailer(m_oc);
181  }
182 
183  if (m_oc )
184  {
185  if (m_oc->pb)
186  {
187  av_freep(&m_oc->pb);
188  }
189  avformat_free_context(m_oc);
190  m_oc = nullptr;
191  }
192 }
unsigned char m_buffer[AudioOutput::MAX_SIZE_BUFFER]
Definition: spdifencoder.h:34
void WriteFrame(unsigned char *data, int size)
Encode data through created muxer unsigned char data: pointer to data to encode int size: size of dat...
static int funcIO(void *opaque, unsigned char *buf, int size)
funcIO: Internal callback function that will receive encoded frames
bool SetMaxHDRate(int rate)
Set the maximum HD rate.
AVFormatContext * m_oc
Definition: spdifencoder.h:33
SPDIFEncoder(const QString &muxer, AVCodecID codec_id)
SPDIFEncoder constructor Args: QString muxer : name of the muxer.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define LOC
void Reset()
Reset the internal encoder buffer.
int GetData(unsigned char *buffer, int &dest_size)
Retrieve encoded data and copy it in the provided buffer.
void Destroy()
Destroy and free all allocated memory.