MythTV  master
spdifencoder.cpp
Go to the documentation of this file.
1 #include "libmythbase/compat.h"
4 
5 #include "spdifencoder.h"
6 
7 extern "C" {
8 #include "libavformat/avformat.h"
9 #include "libavutil/opt.h"
10 }
11 
12 #define LOC QString("SPDIFEncoder: ")
13 
23 SPDIFEncoder::SPDIFEncoder(const QString& muxer, AVCodecID codec_id)
24 {
25  QByteArray dev_ba = muxer.toLatin1();
26 
27  const AVOutputFormat *fmt = av_guess_format(dev_ba.constData(), nullptr, nullptr);
28  if (!fmt)
29  {
30  LOG(VB_AUDIO, LOG_ERR, LOC + "av_guess_format");
31  return;
32  }
33 
34  m_oc = avformat_alloc_context();
35  if (!m_oc)
36  {
37  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_alloc_context");
38  return;
39  }
40  m_oc->oformat = fmt;
41 
42  auto *buffer = (unsigned char *)av_malloc(AudioOutput::kMaxSizeBuffer);
43  m_oc->pb = avio_alloc_context(buffer, AudioOutput::kMaxSizeBuffer, 1,
44  this, nullptr, funcIO, nullptr);
45  if (!m_oc->pb)
46  {
47  LOG(VB_AUDIO, LOG_ERR, LOC + "avio_alloc_context");
48  Destroy();
49  return;
50  }
51 
52  m_oc->pb->seekable = 0;
53  m_oc->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
54 
55  const AVCodec *codec = avcodec_find_decoder(codec_id);
56  if (!codec)
57  {
58  LOG(VB_AUDIO, LOG_ERR, LOC + "avcodec_find_decoder");
59  Destroy();
60  return;
61  }
62 
63  AVStream *stream = avformat_new_stream(m_oc, nullptr);
64  if (!stream)
65  {
66  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_new_stream");
67  Destroy();
68  return;
69  }
70 
71  stream->id = 1;
72  stream->codecpar->codec_id = codec->id;
73  stream->codecpar->codec_type = codec->type;
74  stream->codecpar->sample_rate = 48000; // dummy rate, so codecpar initialization doesn't fail.
75 
76  if (avformat_write_header(m_oc, nullptr) < 0)
77  {
78  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_write_header");
79  Destroy();
80  return;
81  }
82 
83  LOG(VB_AUDIO, LOG_INFO, LOC + QString("Creating %1 encoder (for %2)")
84  .arg(muxer, avcodec_get_name(codec_id)));
85 
86  m_complete = true;
87 }
88 
90 {
91  Destroy();
92 }
93 
99 void SPDIFEncoder::WriteFrame(unsigned char *data, int size)
100 {
101  AVPacket *packet = av_packet_alloc();
102  if (packet == nullptr)
103  {
104  LOG(VB_GENERAL, LOG_ERR, "packet allocation failed");
105  return;
106  }
107 
108  static int s_pts = 1; // to avoid warning "Encoder did not produce proper pts"
109  packet->pts = s_pts++;
110  packet->data = data;
111  packet->size = size;
112 
113  if (av_write_frame(m_oc, packet) < 0)
114  {
115  LOG(VB_AUDIO, LOG_ERR, LOC + "av_write_frame");
116  }
117 
118  av_packet_free(&packet);
119 }
120 
127 int SPDIFEncoder::GetData(unsigned char *buffer, size_t &dest_size)
128 {
129  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
130  {
131  LOG(VB_AUDIO, LOG_ERR, LOC + "GetData");
132  return -1;
133  }
134 
135  if(m_size > 0)
136  {
137  memcpy(buffer, m_oc->pb->buffer, m_size);
138  dest_size = m_size;
139  m_size = 0;
140  return dest_size;
141  }
142  return -1;
143 }
144 
146 {
147  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
148  return -1;
149  return m_size;
150 }
151 
153 {
154  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
155  return nullptr;
156  return m_oc->pb->buffer;
157 }
158 
163 {
164  m_size = 0;
165 }
166 
174 {
175  if (!m_oc)
176  {
177  return false;
178  }
179  av_opt_set_int(m_oc->priv_data, "dtshd_rate", rate, 0);
180  return true;
181 }
182 
186 int SPDIFEncoder::funcIO(void *opaque, unsigned char *buf, int size)
187 {
188  auto *enc = static_cast<SPDIFEncoder *>(opaque);
189 
190  if ((enc->m_oc == nullptr) || (enc->m_oc->pb == nullptr))
191  {
192  LOG(VB_AUDIO, LOG_ERR, LOC + "funcIO");
193  return 0;
194  }
195 
196  memcpy(enc->m_oc->pb->buffer + enc->m_size, buf, size);
197  enc->m_size += size;
198  return size;
199 }
200 
205 {
206  Reset();
207 
208  if (m_complete)
209  {
210  av_write_trailer(m_oc);
211  }
212 
213  if (m_oc )
214  {
215  if (m_oc->pb)
216  {
217  av_free(m_oc->pb->buffer);
218  av_freep(reinterpret_cast<void*>(&m_oc->pb));
219  }
220  avformat_free_context(m_oc);
221  m_oc = nullptr;
222  }
223 }
AudioOutput::kMaxSizeBuffer
static const int kMaxSizeBuffer
kMaxSizeBuffer is the maximum size of a buffer to be used with DecodeAudio
Definition: audiooutput.h:197
SPDIFEncoder::m_oc
AVFormatContext * m_oc
Definition: spdifencoder.h:33
spdifencoder.h
SPDIFEncoder::m_complete
bool m_complete
Definition: spdifencoder.h:32
SPDIFEncoder::funcIO
static int funcIO(void *opaque, unsigned char *buf, int size)
funcIO: Internal callback function that will receive encoded frames
Definition: spdifencoder.cpp:186
SPDIFEncoder::Reset
void Reset()
Reset the internal encoder buffer.
Definition: spdifencoder.cpp:162
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
mythlogging.h
LOC
#define LOC
Definition: spdifencoder.cpp:12
compat.h
SPDIFEncoder::SetMaxHDRate
bool SetMaxHDRate(int rate)
Set the maximum HD rate.
Definition: spdifencoder.cpp:173
SPDIFEncoder::GetProcessedSize
int GetProcessedSize()
Definition: spdifencoder.cpp:145
SPDIFEncoder::WriteFrame
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...
Definition: spdifencoder.cpp:99
SPDIFEncoder::GetData
int GetData(unsigned char *buffer, size_t &dest_size)
Retrieve encoded data and copy it in the provided buffer.
Definition: spdifencoder.cpp:127
mythcorecontext.h
SPDIFEncoder::Destroy
void Destroy()
Destroy and free all allocated memory.
Definition: spdifencoder.cpp:204
SPDIFEncoder::GetProcessedBuffer
unsigned char * GetProcessedBuffer()
Definition: spdifencoder.cpp:152
SPDIFEncoder::SPDIFEncoder
SPDIFEncoder(const QString &muxer, AVCodecID codec_id)
SPDIFEncoder constructor Args: QString muxer : name of the muxer.
Definition: spdifencoder.cpp:23
SPDIFEncoder::~SPDIFEncoder
~SPDIFEncoder()
Definition: spdifencoder.cpp:89
SPDIFEncoder
Definition: spdifencoder.h:14
SPDIFEncoder::m_size
long m_size
Definition: spdifencoder.h:34