Permalink
Browse files

Use SSE accelerated floating point conversions.

AudioBuffer class was using QByteArray which can't be memory aligned. Re-implement it using our own buffer data type
  • Loading branch information...
jyavenard committed Jul 17, 2012
1 parent fa1571c commit 89a2520f1eea6989ec27b2a300e1222866a7a5c2
Showing with 64 additions and 32 deletions.
  1. +0 −10 mythtv/libs/libmythtv/avformatwriter.cpp
  2. +64 −22 mythtv/programs/mythtranscode/transcode.cpp
@@ -340,18 +340,8 @@ bool AVFormatWriter::WriteAudioFrame(unsigned char *buf, int fnum, int timecode)
if (m_audioStream->codec->sample_fmt == AV_SAMPLE_FMT_FLT)
{
-#if 1
- int i = 0;
- float f = 1.0f / ((1<<15) - 1);
- float *out = m_audioFltBuf;
- short *in = (short int *)buf;
-
- for (; i < (m_audioFrameSize * m_audioChannels); i++)
- *out++ = *in++ * f;
-#else
AudioOutputUtil::toFloat(FORMAT_S16, (void *)m_audioFltBuf, (void *)buf,
m_audioFrameSize * 2 * m_audioChannels);
-#endif
m_audPicture->data[0] = (unsigned char *)m_audioFltBuf;
}
else
@@ -9,7 +9,7 @@
#include <QWaitCondition>
#include <QMutex>
#include <QMutexLocker>
-#include <QByteArray>
+#include <QtAlgorithms>
#include "mythconfig.h"
@@ -39,25 +39,69 @@ using namespace std;
#define LOC QString("Transcode: ")
+#define ABLOCK_SIZE 8192
+
class AudioBuffer
{
public:
- AudioBuffer() : m_buffer(QByteArray()), m_frames(0), m_time(-1) {};
- AudioBuffer(const AudioBuffer &old) : m_buffer(old.m_buffer),
- m_frames(old.m_frames), m_time(old.m_time) {};
+ AudioBuffer() : m_frames(0), m_time(-1)
+ {
+ m_size = 0;
+ m_buffer = (uint8_t *)av_malloc(ABLOCK_SIZE);
+ if (m_buffer == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ m_realsize = ABLOCK_SIZE;
+ }
- ~AudioBuffer() {};
+ AudioBuffer(const AudioBuffer &old) : m_size(old.m_size),
+ m_realsize(old.m_realsize), m_frames(old.m_frames), m_time(old.m_time)
+ {
+ m_buffer = (uint8_t *)av_malloc(m_realsize);
+ if (m_buffer == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ memcpy(m_buffer, old.m_buffer, m_size);
+ }
+
+ ~AudioBuffer()
+ {
+ av_free(m_buffer);
+ }
void appendData(unsigned char *buffer, int len, int frames, long long time)
{
- m_buffer.append((const char *)buffer, len);
+ if ((m_size + len) > m_realsize)
+ {
+ // buffer is too small to fit all
+ // can't use av_realloc as it doesn't guarantee reallocated memory
+ // to be 16 bytes aligned
+ m_realsize = ((m_size + len) / ABLOCK_SIZE + 1 ) * ABLOCK_SIZE;
+ uint8_t *tmp = (uint8_t *)av_malloc(m_realsize);
+ if (tmp == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ memcpy(tmp, m_buffer, m_size);
+ av_free(m_buffer);
+ m_buffer = tmp;
+ }
+ memcpy(m_buffer + m_size, buffer, len);
+ m_size += len;
m_frames += frames;
- m_time = time;
+ m_time = time;
}
- QByteArray m_buffer;
- int m_frames;
- long long m_time;
+ char *data(void) { return (char *)m_buffer; }
+ int size(void) { return m_size; }
+
+ uint8_t *m_buffer;
+ int m_size;
+ int m_realsize;
+ int m_frames;
+ long long m_time;
};
// This class is to act as a fake audio output device to store the data
@@ -104,12 +148,11 @@ class AudioReencodeBuffer : public AudioOutput
virtual void Reset(void)
{
QMutexLocker locker(&m_bufferMutex);
- for (QList<AudioBuffer *>::iterator it = m_bufferList.begin();
- it != m_bufferList.end(); it = m_bufferList.erase(it))
+ foreach (AudioBuffer *ab, m_bufferList)
{
- AudioBuffer *ab = *it;
delete ab;
}
+ m_bufferList.clear();
}
// timecode is in milliseconds.
@@ -140,7 +183,7 @@ class AudioReencodeBuffer : public AudioOutput
// Use as many of the remaining frames as will fit in the space
// left in the buffer.
- int bufsize = m_saveBuffer->m_buffer.size();
+ int bufsize = m_saveBuffer->size();
int part = min(len - index, m_audioFrameSize - bufsize);
total_frames += part / m_bytes_per_frame;
timecode += total_frames * 1000 / m_eff_audiorate;
@@ -150,7 +193,7 @@ class AudioReencodeBuffer : public AudioOutput
part / m_bytes_per_frame, timecode);
// If we have filled the buffer...
- if (m_saveBuffer->m_buffer.size() == m_audioFrameSize)
+ if (m_saveBuffer->size() == m_audioFrameSize)
{
QMutexLocker locker(&m_bufferMutex);
@@ -515,7 +558,7 @@ class Cutter
else
{
// Don't drop this packet even though we still have frames to cut,
- // because doing so would put us further out. Instead, inflate the
+ // because doing so would put us further out. Instead, inflate the
// callers record of how many audio frames have been output.
*totalAudio += audioFramesToCut;
audioFramesToCut = 0;
@@ -1680,8 +1723,7 @@ int Transcode::TranscodeFile(const QString &inputname,
if (!cutter ||
!cutter->InhibitUseAudioFrames(ab->m_frames, &totalAudio))
- fifow->FIFOWrite(1, ab->m_buffer.data(),
- ab->m_buffer.size());
+ fifow->FIFOWrite(1, ab->data(), ab->size());
delete ab;
}
@@ -1887,7 +1929,7 @@ int Transcode::TranscodeFile(const QString &inputname,
for (loop = 0; loop < count; loop++)
{
AudioBuffer *ab = arb->GetData();
- unsigned char *buf = (unsigned char *)ab->m_buffer.data();
+ unsigned char *buf = (unsigned char *)ab->data();
if (avfMode)
{
if (did_ff != 1)
@@ -1913,7 +1955,7 @@ int Transcode::TranscodeFile(const QString &inputname,
}
else
{
- nvr->SetOption("audioframesize", ab->m_buffer.size());
+ nvr->SetOption("audioframesize", ab->size());
nvr->WriteAudio(buf, audioFrame++,
ab->m_time - timecodeOffset);
if (nvr->IsErrored())
@@ -1932,12 +1974,12 @@ int Transcode::TranscodeFile(const QString &inputname,
}
++buffersConsumed;
- bytesConsumed += ab->m_buffer.size();
+ bytesConsumed += ab->size();
delete ab;
}
- LOG(VB_GENERAL, LOG_DEBUG,
+ LOG(VB_GENERAL, LOG_DEBUG,
QString("Processed %1 audio frames for timecode %2: %3 "
"buffers, %4 bytes consumed")
.arg(count) .arg(frame.timecode) .arg(buffersConsumed)

0 comments on commit 89a2520

Please sign in to comment.