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  QByteArray dev_ba = muxer.toLatin1();
27 
28  AVOutputFormat *fmt = av_guess_format(dev_ba.constData(), nullptr, nullptr);
29  if (!fmt)
30  {
31  LOG(VB_AUDIO, LOG_ERR, LOC + "av_guess_format");
32  return;
33  }
34 
35  m_oc = avformat_alloc_context();
36  if (!m_oc)
37  {
38  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_alloc_context");
39  return;
40  }
41  m_oc->oformat = fmt;
42 
43  auto *buffer = (unsigned char *)av_malloc(AudioOutput::kMaxSizeBuffer);
44  m_oc->pb = avio_alloc_context(buffer, AudioOutput::kMaxSizeBuffer, 1,
45  this, nullptr, funcIO, nullptr);
46  if (!m_oc->pb)
47  {
48  LOG(VB_AUDIO, LOG_ERR, LOC + "avio_alloc_context");
49  Destroy();
50  return;
51  }
52 
53  m_oc->pb->seekable = 0;
54  m_oc->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
55 
56  const AVCodec *codec = avcodec_find_decoder(codec_id);
57  if (!codec)
58  {
59  LOG(VB_AUDIO, LOG_ERR, LOC + "avcodec_find_decoder");
60  Destroy();
61  return;
62  }
63 
64  AVStream *stream = avformat_new_stream(m_oc, nullptr);
65  if (!stream)
66  {
67  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_new_stream");
68  Destroy();
69  return;
70  }
71 
72  stream->id = 1;
73  stream->codecpar->codec_id = codec->id;
74  stream->codecpar->codec_type = codec->type;
75  stream->codecpar->sample_rate = 48000; // dummy rate, so codecpar initialization doesn't fail.
76 
77  if (avformat_write_header(m_oc, nullptr) < 0)
78  {
79  LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_write_header");
80  Destroy();
81  return;
82  }
83 
84  LOG(VB_AUDIO, LOG_INFO, LOC + QString("Creating %1 encoder (for %2)")
85  .arg(muxer).arg(ff_codec_id_string(codec_id)));
86 
87  m_complete = true;
88 }
89 
91 {
92  Destroy();
93 }
94 
100 void SPDIFEncoder::WriteFrame(unsigned char *data, int size)
101 {
102  AVPacket packet;
103  av_init_packet(&packet);
104  static int s_pts = 1; // to avoid warning "Encoder did not produce proper pts"
105  packet.pts = s_pts++;
106  packet.data = data;
107  packet.size = size;
108 
109  if (av_write_frame(m_oc, &packet) < 0)
110  {
111  LOG(VB_AUDIO, LOG_ERR, LOC + "av_write_frame");
112  }
113 }
114 
121 int SPDIFEncoder::GetData(unsigned char *buffer, size_t &dest_size)
122 {
123  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
124  {
125  LOG(VB_AUDIO, LOG_ERR, LOC + "GetData");
126  return -1;
127  }
128 
129  if(m_size > 0)
130  {
131  memcpy(buffer, m_oc->pb->buffer, m_size);
132  dest_size = m_size;
133  m_size = 0;
134  return dest_size;
135  }
136  return -1;
137 }
138 
140 {
141  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
142  return -1;
143  return m_size;
144 }
145 
147 {
148  if ((m_oc == nullptr) || (m_oc->pb == nullptr))
149  return nullptr;
150  return m_oc->pb->buffer;
151 }
152 
157 {
158  m_size = 0;
159 }
160 
168 {
169  if (!m_oc)
170  {
171  return false;
172  }
173  av_opt_set_int(m_oc->priv_data, "dtshd_rate", rate, 0);
174  return true;
175 }
176 
180 int SPDIFEncoder::funcIO(void *opaque, unsigned char *buf, int size)
181 {
182  auto *enc = static_cast<SPDIFEncoder *>(opaque);
183 
184  if ((enc->m_oc == nullptr) || (enc->m_oc->pb == nullptr))
185  {
186  LOG(VB_AUDIO, LOG_ERR, LOC + "funcIO");
187  return 0;
188  }
189 
190  memcpy(enc->m_oc->pb->buffer + enc->m_size, buf, size);
191  enc->m_size += size;
192  return size;
193 }
194 
199 {
200  Reset();
201 
202  if (m_complete)
203  {
204  av_write_trailer(m_oc);
205  }
206 
207  if (m_oc )
208  {
209  if (m_oc->pb)
210  {
211  av_free(m_oc->pb->buffer);
212  av_freep(&m_oc->pb);
213  }
214  avformat_free_context(m_oc);
215  m_oc = nullptr;
216  }
217 }
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:180
SPDIFEncoder::Reset
void Reset()
Reset the internal encoder buffer.
Definition: spdifencoder.cpp:156
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
mythlogging.h
LOC
#define LOC
Definition: spdifencoder.cpp:13
compat.h
SPDIFEncoder::SetMaxHDRate
bool SetMaxHDRate(int rate)
Set the maximum HD rate.
Definition: spdifencoder.cpp:167
SPDIFEncoder::GetProcessedSize
int GetProcessedSize()
Definition: spdifencoder.cpp:139
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:100
SPDIFEncoder::GetData
int GetData(unsigned char *buffer, size_t &dest_size)
Retrieve encoded data and copy it in the provided buffer.
Definition: spdifencoder.cpp:121
mythcorecontext.h
SPDIFEncoder::Destroy
void Destroy()
Destroy and free all allocated memory.
Definition: spdifencoder.cpp:198
SPDIFEncoder::GetProcessedBuffer
unsigned char * GetProcessedBuffer()
Definition: spdifencoder.cpp:146
SPDIFEncoder::SPDIFEncoder
SPDIFEncoder(const QString &muxer, AVCodecID codec_id)
SPDIFEncoder constructor Args: QString muxer : name of the muxer.
Definition: spdifencoder.cpp:24
SPDIFEncoder::~SPDIFEncoder
~SPDIFEncoder()
Definition: spdifencoder.cpp:90
SPDIFEncoder
Definition: spdifencoder.h:14
SPDIFEncoder::m_size
long m_size
Definition: spdifencoder.h:34