Updating version info in Win32 portions
[asdcplib.git] / src / PCMParserList.cpp
1 /*
2 Copyright (c) 2004-2009, 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    PCMParserList.cpp
28     \version $Id$
29     \brief   Read WAV file(s), multiplex multiple PCM frame buffers into one
30 */
31
32 #include <PCMParserList.h>
33 #include <KM_fileio.h>
34 #include <KM_log.h>
35 #include <assert.h>
36
37 using namespace ASDCP;
38 using namespace Kumu;
39
40
41 ASDCP::ParserInstance::ParserInstance() : m_p(0), m_SampleSize(0)
42 {
43 }
44
45 ASDCP::ParserInstance::~ParserInstance()
46 {
47 }
48
49 // PCM::CalcSampleSize(ADesc);
50 Result_t
51 ASDCP::ParserInstance::OpenRead(const char* filename, Rational& PictureRate)
52 {
53   ASDCP_TEST_NULL_STR(filename);
54
55   Result_t result = Parser.OpenRead(filename, PictureRate);
56
57   if ( ASDCP_SUCCESS(result) )
58     result = Parser.FillAudioDescriptor(ADesc);
59
60   if ( ASDCP_SUCCESS(result) )
61     {
62       ADesc.EditRate = PictureRate;
63       m_SampleSize = PCM::CalcSampleSize(ADesc);
64       result = FB.Capacity(PCM::CalcFrameBufferSize(ADesc));
65     }
66
67   return result;
68 }
69
70
71 // deposit the next available sample into the given framebuffer
72 Result_t
73 ASDCP::ParserInstance::PutSample(byte_t* p)
74 {
75   ASDCP_TEST_NULL(p);
76
77   memcpy(p, m_p, m_SampleSize);
78   m_p += m_SampleSize;
79   return RESULT_OK;
80 }
81
82
83 //
84 Result_t
85 ASDCP::ParserInstance::ReadFrame()
86 {
87   Result_t result = Parser.ReadFrame(FB);
88   m_p = ASDCP_SUCCESS(result) ? FB.RoData() : 0;
89   return result;
90 }
91
92
93 //------------------------------------------------------------------------------------------
94 //
95
96
97 //
98 ASDCP::PCMParserList::PCMParserList() : m_ChannelCount(0)
99 {
100 }
101
102 ASDCP::PCMParserList::~PCMParserList()
103 {
104   while ( ! empty() )
105     {
106       delete back();
107       pop_back();
108     }
109 }
110
111
112 //
113 Result_t
114 ASDCP::PCMParserList::OpenRead(ui32_t argc, const char** argv, Rational& PictureRate)
115 {
116   ASDCP_TEST_NULL_STR(argv);
117   Result_t result = RESULT_OK;
118   PathList_t::iterator fi;
119   PathList_t TmpFileList;
120
121   if ( argc == 1 && PathIsDirectory(argv[0]) )
122     {
123       DirScanner Dir;
124       char name_buf[MaxFilePath];
125       result = Dir.Open(argv[0]);
126
127       if ( KM_SUCCESS(result) )
128         result = Dir.GetNext(name_buf);
129
130       while ( KM_SUCCESS(result) )
131         {
132           if ( name_buf[0] != '.' ) // no hidden files
133             {
134               std::string tmp_path = std::string(argv[0]) + "/" + name_buf;
135               TmpFileList.push_back(tmp_path);
136             }
137
138           result = Dir.GetNext(name_buf);
139         }
140
141       if ( result == RESULT_ENDOFFILE )
142         {
143           result = RESULT_OK;
144           TmpFileList.sort();
145         }
146     }
147   else
148     {
149       for ( ui32_t i = 0; i < argc; ++i )
150         TmpFileList.push_back(argv[i]);
151     }
152
153   for ( fi = TmpFileList.begin(); KM_SUCCESS(result) && fi != TmpFileList.end(); fi++ )
154     {
155       mem_ptr<ParserInstance> I = new ParserInstance;
156       result = I->OpenRead(fi->c_str(), PictureRate);
157
158       if ( ASDCP_SUCCESS(result) )
159         {
160           if ( fi == TmpFileList.begin() )
161             {
162               m_ADesc = I->ADesc;
163             }
164           else
165             {
166               if ( I->ADesc.AudioSamplingRate != m_ADesc.AudioSamplingRate )
167                 {
168                   DefaultLogSink().Error("AudioSamplingRate mismatch in PCM parser list.");
169                   return RESULT_FORMAT;
170                 }
171
172               if ( I->ADesc.QuantizationBits  != m_ADesc.QuantizationBits )
173                 {
174                   DefaultLogSink().Error("QuantizationBits mismatch in PCM parser list.");
175                   return RESULT_FORMAT;
176                 }
177
178               if ( I->ADesc.ContainerDuration < m_ADesc.ContainerDuration )
179                 m_ADesc.ContainerDuration = I->ADesc.ContainerDuration;
180
181               m_ADesc.BlockAlign += I->ADesc.BlockAlign;
182             }
183
184           m_ChannelCount += I->ADesc.ChannelCount;
185         }
186
187       if ( ASDCP_SUCCESS(result) )
188         result = I->FB.Capacity(PCM::CalcFrameBufferSize(m_ADesc));
189
190       if ( ASDCP_SUCCESS(result) )
191         {
192           push_back(I);
193           I.release();
194         }
195     }
196
197   if ( ASDCP_SUCCESS(result) )
198     {
199       m_ADesc.ChannelCount = m_ChannelCount;
200       m_ADesc.AvgBps = ceil(m_ADesc.AudioSamplingRate.Quotient()) * m_ADesc.BlockAlign;
201     }
202   else
203     {
204       clear();
205     }
206
207   return result;
208 }
209
210 //
211 Result_t
212 ASDCP::PCMParserList::FillAudioDescriptor(PCM::AudioDescriptor& ADesc) const
213 {
214   ADesc = m_ADesc;
215   return RESULT_OK;
216 }
217
218 //
219 Result_t
220 ASDCP::PCMParserList::Reset()
221 {
222   Result_t result = RESULT_OK;
223   PCMParserList::iterator self_i;
224
225   for ( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result) ; self_i++ )
226     result = (*self_i)->Parser.Reset();
227
228   return result;
229 }
230
231
232 //
233 Result_t
234 ASDCP::PCMParserList::ReadFrame(PCM::FrameBuffer& OutFB)
235 {
236   Result_t result = RESULT_OK;
237
238   if ( size() == 1 )
239     return front()->Parser.ReadFrame(OutFB);
240
241   PCMParserList::iterator self_i;
242   assert(PCM::CalcFrameBufferSize(m_ADesc) <= OutFB.Capacity());
243
244   for ( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result) ; self_i++ )
245     result = (*self_i)->ReadFrame();
246
247   if ( ASDCP_SUCCESS(result) )
248     {
249       OutFB.Size(PCM::CalcFrameBufferSize(m_ADesc));
250
251       //      ui32_t sample_size = (PCM::CalcSampleSize(m_ADesc));
252       byte_t* Out_p = OutFB.Data();
253       byte_t* End_p = Out_p + OutFB.Size();
254
255       while ( Out_p < End_p && ASDCP_SUCCESS(result) )
256         {
257           self_i = begin();
258
259           while ( self_i != end() && ASDCP_SUCCESS(result) )
260             {
261               result = (*self_i)->PutSample(Out_p);
262               Out_p += (*self_i)->SampleSize();
263               self_i++;
264             }
265         }
266
267       assert(Out_p == End_p);
268     }
269
270   return result;
271 }
272
273 //
274 // end PCMParserList.cpp
275 //