diff options
Diffstat (limited to 'xbmc/cdrip/Encoder.cpp')
-rw-r--r-- | xbmc/cdrip/Encoder.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/xbmc/cdrip/Encoder.cpp b/xbmc/cdrip/Encoder.cpp new file mode 100644 index 0000000..fa78f84 --- /dev/null +++ b/xbmc/cdrip/Encoder.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "Encoder.h" + +#include "filesystem/File.h" +#include "utils/log.h" + +#include <string.h> +#include <utility> + +using namespace KODI::CDRIP; + +CEncoder::CEncoder() = default; + +CEncoder::~CEncoder() +{ + FileClose(); +} + +bool CEncoder::EncoderInit(const std::string& strFile, int iInChannels, int iInRate, int iInBits) +{ + m_dwWriteBufferPointer = 0; + m_strFile = strFile; + m_iInChannels = iInChannels; + m_iInSampleRate = iInRate; + m_iInBitsPerSample = iInBits; + + if (!FileCreate(strFile)) + { + CLog::Log(LOGERROR, "CEncoder::{} - Cannot open file: {}", __func__, strFile); + return false; + } + + return Init(); +} + +ssize_t CEncoder::EncoderEncode(uint8_t* pbtStream, size_t nNumBytesRead) +{ + const int iBytes = Encode(pbtStream, nNumBytesRead); + if (iBytes < 0) + { + CLog::Log(LOGERROR, "CEncoder::{} - Internal encoder error: {}", __func__, iBytes); + return 0; + } + return 1; +} + +bool CEncoder::EncoderClose() +{ + if (!Close()) + return false; + + FlushStream(); + FileClose(); + + return true; +} + +bool CEncoder::FileCreate(const std::string& filename) +{ + m_file = std::make_unique<XFILE::CFile>(); + if (m_file) + return m_file->OpenForWrite(filename, true); + return false; +} + +bool CEncoder::FileClose() +{ + if (m_file) + { + m_file->Close(); + m_file.reset(); + } + return true; +} + +// return total bytes written, or -1 on error +ssize_t CEncoder::FileWrite(const uint8_t* pBuffer, size_t iBytes) +{ + if (!m_file) + return -1; + + const ssize_t dwBytesWritten = m_file->Write(pBuffer, iBytes); + if (dwBytesWritten <= 0) + return -1; + + return dwBytesWritten; +} + +ssize_t CEncoder::Seek(ssize_t iFilePosition, int iWhence) +{ + if (!m_file) + return -1; + FlushStream(); + return m_file->Seek(iFilePosition, iWhence); +} + +// write the stream to our writebuffer, and write the buffer to disk if it's full +ssize_t CEncoder::Write(const uint8_t* pBuffer, size_t iBytes) +{ + if ((WRITEBUFFER_SIZE - m_dwWriteBufferPointer) > iBytes) + { + // writebuffer is big enough to fit data + memcpy(m_btWriteBuffer + m_dwWriteBufferPointer, pBuffer, iBytes); + m_dwWriteBufferPointer += iBytes; + return iBytes; + } + else + { + // buffer is not big enough to fit data + if (m_dwWriteBufferPointer == 0) + { + // nothing in our buffer, just write the entire pBuffer to disk + return FileWrite(pBuffer, iBytes); + } + + const size_t dwBytesRemaining = iBytes - (WRITEBUFFER_SIZE - m_dwWriteBufferPointer); + // fill up our write buffer and write it to disk + memcpy(m_btWriteBuffer + m_dwWriteBufferPointer, pBuffer, + (WRITEBUFFER_SIZE - m_dwWriteBufferPointer)); + FileWrite(m_btWriteBuffer, WRITEBUFFER_SIZE); + m_dwWriteBufferPointer = 0; + + // pbtRemaining = pBuffer + bytesWritten + const uint8_t* pbtRemaining = pBuffer + (iBytes - dwBytesRemaining); + if (dwBytesRemaining > WRITEBUFFER_SIZE) + { + // data is not going to fit in our buffer, just write it to disk + if (FileWrite(pbtRemaining, dwBytesRemaining) == -1) + return -1; + return iBytes; + } + else + { + // copy remaining bytes to our currently empty writebuffer + memcpy(m_btWriteBuffer, pbtRemaining, dwBytesRemaining); + m_dwWriteBufferPointer = dwBytesRemaining; + return iBytes; + } + } +} + +// flush the contents of our writebuffer +ssize_t CEncoder::FlushStream() +{ + if (m_dwWriteBufferPointer == 0) + return 0; + + const ssize_t iResult = FileWrite(m_btWriteBuffer, m_dwWriteBufferPointer); + m_dwWriteBufferPointer = 0; + + return iResult; +} |