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