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  m_oc->pb = avio_alloc_context(m_buffer, sizeof(m_buffer), 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).arg(ff_codec_id_string(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;
102  av_init_packet(&packet);
103  static int pts = 1; // to avoid warning "Encoder did not produce proper pts"
104  packet.pts = pts++;
105  packet.data = data;
106  packet.size = size;
107 
108  if (av_write_frame(m_oc, &packet) < 0)
109  {
110  LOG(VB_AUDIO, LOG_ERR, LOC + "av_write_frame");
111  }
112 }
113 
120 int SPDIFEncoder::GetData(unsigned char *buffer, int &dest_size)
121 {
122  if(m_size > 0)
123  {
124  memcpy(buffer, m_buffer, m_size);
125  dest_size = m_size;
126  m_size = 0;
127  return dest_size;
128  }
129  return -1;
130 }
131 
136 {
137  m_size = 0;
138 }
139 
147 {
148  if (!m_oc)
149  {
150  return false;
151  }
152  av_opt_set_int(m_oc->priv_data, "dtshd_rate", rate, 0);
153  return true;
154 }
155 
159 int SPDIFEncoder::funcIO(void *opaque, unsigned char *buf, int size)
160 {
161  SPDIFEncoder *enc = (SPDIFEncoder *)opaque;
162 
163  memcpy(enc->m_buffer + enc->m_size, buf, size);
164  enc->m_size += size;
165  return size;
166 }
167 
172 {
173  Reset();
174 
175  if (m_complete)
176  {
177  av_write_trailer(m_oc);
178  }
179 
180  if (m_oc )
181  {
182  if (m_oc->pb)
183  {
184  av_freep(&m_oc->pb);
185  }
186  avformat_free_context(m_oc);
187  m_oc = nullptr;
188  }
189 }
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.