wheee!
[asdcplib.git] / src / PCM_Parser.cpp
1 /*
2 Copyright (c) 2004, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14    derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 /*! \file    PCM_Parser.cpp
28     \version $Id$
29     \brief   AS-DCP library, PCM raw essence reader implementation
30 */
31
32 #include <Wav.h>
33 #include <assert.h>
34
35 using namespace ASDCP;
36 using namespace ASDCP::PCM;
37 using namespace ASDCP::Wav;
38
39
40 //------------------------------------------------------------------------------------------
41
42 //
43 class ASDCP::PCM::WAVParser::h__WAVParser
44 {
45   FileReader       m_FileReader;
46   bool             m_EOF;
47   ui32_t           m_DataStart;
48   ui32_t           m_DataLength;
49   ui32_t           m_ReadCount;
50   ui32_t           m_FrameBufferSize;
51   ui32_t           m_FramesRead;
52   Rational         m_PictureRate;
53
54   ASDCP_NO_COPY_CONSTRUCT(h__WAVParser);
55
56 public:
57   AudioDescriptor  m_ADesc;
58
59
60   h__WAVParser() :
61     m_EOF(false), m_DataStart(0), m_DataLength(0), m_ReadCount(0),
62     m_FrameBufferSize(0), m_FramesRead(0) {}
63
64   ~h__WAVParser()
65   {
66     Close();
67    }
68
69   Result_t OpenRead(const char* filename, const Rational& PictureRate);
70   void     Close();
71   void     Reset();
72   Result_t ReadFrame(FrameBuffer&);
73 };
74
75
76 //
77 void
78 ASDCP::PCM::WAVParser::h__WAVParser::Close()
79 {
80   m_FileReader.Close();
81 }
82
83 //
84 void
85 ASDCP::PCM::WAVParser::h__WAVParser::Reset()
86 {
87   m_FileReader.Seek(m_DataStart);
88   m_FramesRead = 0;
89   m_ReadCount = 0;
90 }
91
92 //
93 ASDCP::Result_t
94 ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const char* filename, const Rational& PictureRate)
95 {
96   ASDCP_TEST_NULL_STR(filename);
97   SimpleWaveHeader WavHeader;
98
99   Result_t result = m_FileReader.OpenRead(filename);
100
101   if ( ASDCP_SUCCESS(result) )
102     result = WavHeader.ReadFromFile(m_FileReader, &m_DataStart);
103   
104   if ( ASDCP_SUCCESS(result) )
105     {
106       WavHeader.FillADesc(m_ADesc, PictureRate);
107       m_FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(m_ADesc);
108       m_DataLength = WavHeader.data_len;
109       m_ADesc.ContainerDuration = m_DataLength / m_FrameBufferSize;
110       Reset();
111     }
112
113   return result;
114 }
115
116 //
117 ASDCP::Result_t
118 ASDCP::PCM::WAVParser::h__WAVParser::ReadFrame(FrameBuffer& FB)
119 {
120   FB.Size(0);
121
122   if ( m_EOF || m_ReadCount >= m_DataLength )
123     return RESULT_ENDOFFILE;
124
125   if ( FB.Capacity() < m_FrameBufferSize )
126     {
127       DefaultLogSink().Error("FrameBuf.Capacity: %lu FrameLength: %lu\n",
128                              FB.Capacity(), m_FrameBufferSize);
129       return RESULT_SMALLBUF;
130     }
131
132   ui32_t read_count = 0;
133   Result_t result = m_FileReader.Read(FB.Data(), m_FrameBufferSize, &read_count);
134
135   if ( result == RESULT_ENDOFFILE )
136     {
137       m_EOF = true;
138
139       if ( read_count > 0 )
140         result = RESULT_OK;
141     }
142
143   if ( ASDCP_SUCCESS(result) )
144     {
145       m_ReadCount += read_count;
146       FB.Size(read_count);
147       FB.FrameNumber(m_FramesRead++);
148     }
149
150   return result;
151 }
152
153
154 //------------------------------------------------------------------------------------------
155
156 ASDCP::PCM::WAVParser::WAVParser()
157 {
158 }
159
160 ASDCP::PCM::WAVParser::~WAVParser()
161 {
162 }
163
164 // Opens the stream for reading, parses enough data to provide a complete
165 // set of stream metadata for the MXFWriter below.
166 ASDCP::Result_t
167 ASDCP::PCM::WAVParser::OpenRead(const char* filename, const Rational& PictureRate) const
168 {
169   const_cast<ASDCP::PCM::WAVParser*>(this)->m_Parser = new h__WAVParser;
170
171   Result_t result = m_Parser->OpenRead(filename, PictureRate);
172
173   if ( ASDCP_FAILURE(result) )
174     const_cast<ASDCP::PCM::WAVParser*>(this)->m_Parser.release();
175
176   return result;
177 }
178
179 // Rewinds the stream to the beginning.
180 ASDCP::Result_t
181 ASDCP::PCM::WAVParser::Reset() const
182 {
183   if ( m_Parser.empty() )
184     return RESULT_INIT;
185
186   m_Parser->Reset();
187   return RESULT_OK;
188 }
189
190 // Places a frame of data in the frame buffer. Fails if the buffer is too small
191 // or the stream is empty.
192 ASDCP::Result_t
193 ASDCP::PCM::WAVParser::ReadFrame(FrameBuffer& FB) const
194 {
195   if ( m_Parser.empty() )
196     return RESULT_INIT;
197
198   return m_Parser->ReadFrame(FB);
199 }
200
201 ASDCP::Result_t
202 ASDCP::PCM::WAVParser::FillAudioDescriptor(AudioDescriptor& ADesc) const
203 {
204   if ( m_Parser.empty() )
205     return RESULT_INIT;
206
207   ADesc = m_Parser->m_ADesc;
208   return RESULT_OK;
209 }
210
211
212 //
213 // end PCM_Parser.cpp
214 //