MythTV  master
audioreencodebuffer.cpp
Go to the documentation of this file.
1 
2 #include "audioreencodebuffer.h"
3 
4 #include <algorithm> // for min/max
5 using namespace std;
6 
7 extern "C" {
8 #include "libavutil/mem.h"
9 }
10 
11 
13 {
14  m_buffer = (uint8_t *)av_malloc(ABLOCK_SIZE);
15  if (m_buffer == nullptr)
16  {
17  throw std::bad_alloc();
18  }
19 }
20 
22  : m_size(old.m_size), m_realsize(old.m_realsize),
23  m_frames(old.m_frames), m_time(old.m_time)
24 {
25  m_buffer = (uint8_t *)av_malloc(m_realsize);
26  if (m_buffer == nullptr)
27  {
28  throw std::bad_alloc();
29  }
30  memcpy(m_buffer, old.m_buffer, m_size);
31 }
32 
34 {
36 }
37 
38 void AudioBuffer::appendData(unsigned char *buffer, int len, int frames,
39  long long time)
40 {
41  if ((m_size + len) > m_realsize)
42  {
43  // buffer is too small to fit all
44  // can't use av_realloc as it doesn't guarantee reallocated memory
45  // to be 16 bytes aligned
46  m_realsize = ((m_size + len) / ABLOCK_SIZE + 1 ) * ABLOCK_SIZE;
47  auto *tmp = (uint8_t *)av_malloc(m_realsize);
48  if (tmp == nullptr)
49  {
50  throw std::bad_alloc();
51  }
52  memcpy(tmp, m_buffer, m_size);
54  m_buffer = tmp;
55  }
56 
57  memcpy(m_buffer + m_size, buffer, len);
58  m_size += len;
59  m_frames += frames;
60  m_time = time;
61 }
62 
64 
66  int audio_channels, bool passthru)
67  : m_initpassthru(passthru)
68 {
70  const AudioSettings settings(audio_format, audio_channels, AV_CODEC_ID_NONE, 0, false);
72 }
73 
75 {
77  delete m_saveBuffer;
78 }
79 
84 {
85  ClearError();
86 
87  m_passthru = settings.m_usePassthru;
88  m_channels = settings.m_channels;
91  m_eff_audiorate = settings.m_sampleRate;
92 }
93 
98 {
99  m_eff_audiorate = (dsprate / 100);
100 }
101 
103 {
104  QMutexLocker locker(&m_bufferMutex);
105  for (AudioBuffer *ab : qAsConst(m_bufferList))
106  {
107  delete ab;
108  }
109  m_bufferList.clear();
110 }
111 
122 bool AudioReencodeBuffer::AddFrames(void *buffer, int frames, int64_t timecode)
123 {
124  return AddData(buffer, frames * m_bytes_per_frame, timecode, frames);
125 }
126 
138 bool AudioReencodeBuffer::AddData(void *buffer, int len, int64_t timecode,
139  int frames)
140 {
141  auto *buf = (unsigned char *)buffer;
142 
143  // Test if target is using a fixed buffer size.
144  if (m_audioFrameSize)
145  {
146  int index = 0;
147 
148  // Target has a fixed buffer size, which may not match len.
149  // Redistribute the bytes into appropriately sized buffers.
150  while (index < len)
151  {
152  // See if we have some saved from last iteration in
153  // m_saveBuffer. If not create a new empty buffer.
154  if (!m_saveBuffer)
155  m_saveBuffer = new AudioBuffer();
156 
157  // Use as many of the remaining frames as will fit in the space
158  // left in the buffer.
159  int bufsize = m_saveBuffer->size();
160  int part = min(len - index, m_audioFrameSize - bufsize);
161  int out_frames = part / m_bytes_per_frame;
162  timecode += out_frames * 1000 / m_eff_audiorate;
163 
164  // Store frames in buffer, basing frame count on number of
165  // bytes, which works only for uncompressed data.
166  m_saveBuffer->appendData(&buf[index], part,
167  out_frames, timecode);
168 
169  // If we have filled the buffer...
171  {
172  QMutexLocker locker(&m_bufferMutex);
173 
174  // store the buffer
175  m_bufferList.append(m_saveBuffer);
176  // mark m_saveBuffer as emtpy.
177  m_saveBuffer = nullptr;
178  // m_last_audiotime is updated iff we store a buffer.
179  m_last_audiotime = timecode;
180  }
181 
182  index += part;
183  }
184  }
185  else
186  {
187  // Target has no fixed buffer size. We can use a simpler algorithm
188  // and use 'frames' directly rather than 'len / m_bytes_per_frame',
189  // thus also covering the passthrough case.
190  m_saveBuffer = new AudioBuffer();
191  timecode += frames * 1000 / m_eff_audiorate;
192  m_saveBuffer->appendData(buf, len, frames, timecode);
193 
194  QMutexLocker locker(&m_bufferMutex);
195  m_bufferList.append(m_saveBuffer);
196  m_saveBuffer = nullptr;
197  m_last_audiotime = timecode;
198  }
199 
200  return true;
201 }
202 
204 {
205  QMutexLocker locker(&m_bufferMutex);
206 
207  if (m_bufferList.isEmpty())
208  return nullptr;
209 
210  AudioBuffer *ab = m_bufferList.front();
211 
212  if (ab->m_time <= time)
213  {
214  m_bufferList.pop_front();
215  return ab;
216  }
217 
218  return nullptr;
219 }
220 
221 long long AudioReencodeBuffer::GetSamples(long long time)
222 {
223  QMutexLocker locker(&m_bufferMutex);
224 
225  if (m_bufferList.isEmpty())
226  return 0;
227 
228  long long samples = 0;
229  for (auto *ab : qAsConst(m_bufferList))
230  {
231  if (ab->m_time <= time)
232  samples += ab->m_frames;
233  else
234  break;
235  }
236  return samples;
237 }
238 
239 void AudioReencodeBuffer::SetTimecode(int64_t timecode)
240 {
241  m_last_audiotime = timecode;
242 }
243 
244 /* vim: set expandtab tabstop=4 shiftwidth=4: */
245 
AudioReencodeBuffer::~AudioReencodeBuffer
~AudioReencodeBuffer() override
Definition: audioreencodebuffer.cpp:74
AudioBuffer::m_buffer
uint8_t * m_buffer
Definition: audioreencodebuffer.h:20
samples
static uint64_t samples[4]
Definition: element.cpp:45
AudioReencodeBuffer::m_eff_audiorate
int m_eff_audiorate
Definition: audioreencodebuffer.h:72
AudioReencodeBuffer::AudioReencodeBuffer
AudioReencodeBuffer(AudioFormat audio_format, int audio_channels, bool passthru)
Definition: audioreencodebuffer.cpp:65
AudioReencodeBuffer::m_last_audiotime
long long m_last_audiotime
Definition: audioreencodebuffer.h:73
AudioOutputSettings::SampleSize
static int SampleSize(AudioFormat format)
Definition: audiooutputsettings.cpp:189
AudioBuffer::m_realsize
int m_realsize
Definition: audioreencodebuffer.h:22
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
AudioReencodeBuffer::GetSamples
long long GetSamples(long long time)
Definition: audioreencodebuffer.cpp:221
AudioSettings::m_sampleRate
int m_sampleRate
Definition: audiosettings.h:75
AudioSettings
Definition: audiosettings.h:28
AudioReencodeBuffer::AddData
bool AddData(void *buffer, int len, int64_t timecode, int frames) override
Add data to the audiobuffer for playback.
Definition: audioreencodebuffer.cpp:138
ABLOCK_SIZE
#define ABLOCK_SIZE
Definition: audioreencodebuffer.h:7
AudioReencodeBuffer::Reconfigure
void Reconfigure(const AudioSettings &settings) override
reconfigure sound out for new params
Definition: audioreencodebuffer.cpp:83
AudioBuffer::~AudioBuffer
~AudioBuffer()
Definition: audioreencodebuffer.cpp:33
AudioReencodeBuffer::m_bytes_per_frame
int m_bytes_per_frame
Definition: audioreencodebuffer.h:71
AudioReencodeBuffer::m_saveBuffer
AudioBuffer * m_saveBuffer
Definition: audioreencodebuffer.h:81
AudioReencodeBuffer::SetEffDsp
void SetEffDsp(int dsprate) override
Definition: audioreencodebuffer.cpp:97
AudioReencodeBuffer::m_audioFrameSize
int m_audioFrameSize
Definition: audioreencodebuffer.h:75
av_free
void av_free(void *ptr)
AudioBuffer::size
int size(void) const
Definition: audioreencodebuffer.h:18
AudioReencodeBuffer::Reset
void Reset(void) override
Definition: audioreencodebuffer.cpp:102
AudioReencodeBuffer::SetTimecode
void SetTimecode(int64_t timecode) override
Definition: audioreencodebuffer.cpp:239
AudioBuffer::m_time
long long m_time
Definition: audioreencodebuffer.h:24
AudioBuffer::m_frames
int m_frames
Definition: audioreencodebuffer.h:23
AudioSettings::m_usePassthru
bool m_usePassthru
Definition: audiosettings.h:77
AudioSettings::m_format
AudioFormat m_format
Definition: audiosettings.h:71
AudioBuffer::appendData
void appendData(unsigned char *buffer, int len, int frames, long long time)
Definition: audioreencodebuffer.cpp:38
AudioReencodeBuffer::m_passthru
bool m_passthru
Definition: audioreencodebuffer.h:74
AudioReencodeBuffer::GetData
AudioBuffer * GetData(long long time)
Definition: audioreencodebuffer.cpp:203
AudioReencodeBuffer::m_bufferMutex
QMutex m_bufferMutex
Definition: audioreencodebuffer.h:79
AudioBuffer::m_size
int m_size
Definition: audioreencodebuffer.h:21
AudioOutput::ClearError
void ClearError(void)
Definition: audiooutput.cpp:294
AudioReencodeBuffer::m_bufferList
QList< AudioBuffer * > m_bufferList
Definition: audioreencodebuffer.h:80
AudioBuffer
Definition: audioreencodebuffer.h:9
audioreencodebuffer.h
av_malloc
void * av_malloc(unsigned int size)
AudioBuffer::AudioBuffer
AudioBuffer()
Definition: audioreencodebuffer.cpp:12
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:25
AudioReencodeBuffer::AddFrames
bool AddFrames(void *buffer, int frames, int64_t timecode) override
Add frames to the audiobuffer for playback.
Definition: audioreencodebuffer.cpp:122
AudioReencodeBuffer::m_channels
int m_channels
Definition: audioreencodebuffer.h:70
AudioSettings::m_channels
int m_channels
Definition: audiosettings.h:72