/*
-Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
John Hurst
All rights reserved.
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
/*! \file AS_02_PCM.cpp
\version $Id$
\brief AS-02 library, PCM essence reader and writer implementation
class AS_02::PCM::MXFReader::h__Reader : public AS_02::h__AS02Reader
{
- ui64_t m_ClipEssenceBegin;
- ui64_t m_SamplesPerFrame;
- ui32_t m_BytesPerFrame;
- ui32_t m_ContainerDuration;
+ ui64_t m_ClipEssenceBegin, m_ClipSize;
+ ui32_t m_ClipDurationFrames, m_BytesPerFrame;
ASDCP_NO_COPY_CONSTRUCT(h__Reader);
h__Reader();
public:
- h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d), m_ClipEssenceBegin(0),
- m_SamplesPerFrame(0), m_BytesPerFrame(0), m_ContainerDuration(0) {}
+ h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d), m_ClipEssenceBegin(0), m_ClipSize(0),
+ m_ClipDurationFrames(0) {}
virtual ~h__Reader() {}
ASDCP::Result_t OpenRead(const std::string&, const ASDCP::Rational& edit_rate);
{
if ( ! UL(reader.Key()).MatchIgnoreStream(m_Dict->ul(MDD_WAVEssenceClip)) )
{
- const MDDEntry *entry = m_Dict->FindUL(reader.Key());
+ const MDDEntry *entry = m_Dict->FindULAnyVersion(reader.Key());
if ( entry == 0 )
{
}
m_ClipEssenceBegin = m_File.Tell();
- m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*wave_descriptor, edit_rate);
+ m_ClipSize = reader.Length();
m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, edit_rate);
- m_ContainerDuration = static_cast<ui32_t>(reader.Length() / ( m_SamplesPerFrame * AS_02::MXF::CalcSampleSize(*wave_descriptor)));
+ m_ClipDurationFrames = m_ClipSize / m_BytesPerFrame;
+ if ( m_ClipSize % m_BytesPerFrame > 0 )
+ {
+ ++m_ClipDurationFrames; // there is a partial frame at the end
+ }
}
}
return RESULT_INIT;
}
- if ( FrameNum > m_ContainerDuration )
+ if ( ! ( FrameNum < m_ClipDurationFrames ) )
{
return RESULT_RANGE;
}
assert(m_ClipEssenceBegin);
- ui64_t position = m_ClipEssenceBegin + ( FrameNum * m_BytesPerFrame );
+ ui64_t offset = FrameNum * m_BytesPerFrame;
+ ui64_t position = m_ClipEssenceBegin + offset;
Result_t result = RESULT_OK;
if ( m_File.Tell() != position )
if ( KM_SUCCESS(result) )
{
- result = m_File.Read(FrameBuf.Data(), m_BytesPerFrame);
- }
+ ui64_t remainder = m_ClipSize - offset;
+ ui32_t read_size = ( remainder < m_BytesPerFrame ) ? remainder : m_BytesPerFrame;
+ result = m_File.Read(FrameBuf.Data(), read_size);
- if ( KM_SUCCESS(result) )
- {
- FrameBuf.Size(m_BytesPerFrame);
+ if ( KM_SUCCESS(result) )
+ {
+ FrameBuf.Size(read_size);
+
+ if ( read_size < FrameBuf.Capacity() )
+ {
+ memset(FrameBuf.Data() + FrameBuf.Size(), 0, FrameBuf.Capacity() - FrameBuf.Size());
+ }
+ }
}
return result;
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
ASDCP::Result_t
-AS_02::PCM::MXFReader::OpenRead(const std::string& filename, const ASDCP::Rational& edit_rate)
+AS_02::PCM::MXFReader::OpenRead(const std::string& filename, const ASDCP::Rational& edit_rate) const
{
return m_Reader->OpenRead(filename, edit_rate);
}
AS_02::PCM::MXFReader::DumpHeaderMetadata(FILE* stream) const
{
if ( m_Reader && m_Reader->m_File.IsOpen() )
- m_Reader->m_HeaderPart.Dump(stream);
+ {
+ m_Reader->m_HeaderPart.Dump(stream);
+ }
}
-
//
void
AS_02::PCM::MXFReader::DumpIndex(FILE* stream) const
{
- if ( m_Reader->m_File.IsOpen() )
- m_Reader->m_IndexAccess.Dump(stream);
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ m_Reader->m_IndexAccess.Dump(stream);
+ }
}
public:
ASDCP::MXF::WaveAudioDescriptor *m_WaveAudioDescriptor;
byte_t m_EssenceUL[SMPTE_UL_LENGTH];
- ui32_t m_BytesPerFrame;
- ui32_t m_SamplesPerFrame;
-
- h__Writer(const Dictionary& d) : AS_02::h__AS02WriterClip(d), m_WaveAudioDescriptor(0), m_BytesPerFrame(0), m_SamplesPerFrame(0)
+ ui32_t m_BytesPerSample;
+
+ h__Writer(const Dictionary& d) : AS_02::h__AS02WriterClip(d), m_WaveAudioDescriptor(0), m_BytesPerSample(0)
{
memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
}
if ( KM_SUCCESS(result) )
{
assert(m_WaveAudioDescriptor);
- m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*m_WaveAudioDescriptor, edit_rate);
- m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*m_WaveAudioDescriptor, edit_rate);
- m_WaveAudioDescriptor->ContainerDuration = 0;
- assert(m_BytesPerFrame);
+ m_BytesPerSample = AS_02::MXF::CalcSampleSize(*m_WaveAudioDescriptor);
result = WriteAS02Header(PCM_PACKAGE_LABEL, UL(m_Dict->ul(MDD_WAVWrappingClip)),
SOUND_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_SoundDataDef)),
m_EssenceDescriptor->SampleRate, derive_timecode_rate_from_edit_rate(edit_rate));
return RESULT_PARAM;
}
- if ( frame_buf.Size() % m_BytesPerFrame != 0 )
- {
- DefaultLogSink().Error("The frame buffer does not contain an integral number of sample sets.\n");
- return RESULT_AS02_FORMAT;
- }
-
Result_t result = RESULT_OK;
if ( m_State.Test_READY() )
if ( KM_SUCCESS(result) )
{
- m_FramesWritten += m_SamplesPerFrame;
+ m_FramesWritten += frame_buf.Size() / m_BytesPerSample;
}
return result;
if ( KM_SUCCESS(result) )
{
- m_IndexWriter.m_Duration = m_FramesWritten;
+ m_WaveAudioDescriptor->ContainerDuration = m_IndexWriter.m_Duration = m_FramesWritten;
WriteAS02Footer();
}