version bump
[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_log.h>
34 #include <assert.h>
35
36 using namespace ASDCP;
37 using namespace Kumu;
38
39
40 ASDCP::ParserInstance::ParserInstance() : m_p(0), m_SampleSize(0)
41 {
42 }
43
44 ASDCP::ParserInstance::~ParserInstance()
45 {
46 }
47
48 // PCM::CalcSampleSize(ADesc);
49 Result_t
50 ASDCP::ParserInstance::OpenRead(const char* filename, Rational& PictureRate)
51 {
52   ASDCP_TEST_NULL_STR(filename);
53
54   Result_t result = Parser.OpenRead(filename, PictureRate);
55
56   if ( ASDCP_SUCCESS(result) )
57     result = Parser.FillAudioDescriptor(ADesc);
58
59   if ( ASDCP_SUCCESS(result) )
60     {
61       ADesc.SampleRate = PictureRate;
62       m_SampleSize = PCM::CalcSampleSize(ADesc);
63       result = FB.Capacity(PCM::CalcFrameBufferSize(ADesc));
64     }
65
66   return result;
67 }
68
69
70 // deposit the next available sample into the given framebuffer
71 Result_t
72 ASDCP::ParserInstance::PutSample(byte_t* p)
73 {
74   ASDCP_TEST_NULL(p);
75
76   memcpy(p, m_p, m_SampleSize);
77   m_p += m_SampleSize;
78   return RESULT_OK;
79 }
80
81
82 //
83 Result_t
84 ASDCP::ParserInstance::ReadFrame()
85 {
86   Result_t result = Parser.ReadFrame(FB);
87   m_p = ASDCP_SUCCESS(result) ? FB.RoData() : 0;
88   return result;
89 }
90
91
92 //------------------------------------------------------------------------------------------
93 //
94
95
96 //
97 ASDCP::PCMParserList::PCMParserList() : m_ChannelCount(0)
98 {
99 }
100
101 ASDCP::PCMParserList::~PCMParserList()
102 {
103   while ( ! empty() )
104     {
105       delete back();
106       pop_back();
107     }
108 }
109
110
111 //
112 Result_t
113 ASDCP::PCMParserList::OpenRead(ui32_t argc, const char** argv, Rational& PictureRate)
114 {
115   ASDCP_TEST_NULL_STR(argv);
116   Result_t result = RESULT_OK;
117
118   for ( ui32_t i = 0; i < argc && ASDCP_SUCCESS(result); i++ )
119     {
120       ParserInstance* I = new ParserInstance;
121       result = I->OpenRead(argv[i], PictureRate);
122
123       if ( ASDCP_SUCCESS(result) )
124         {
125           if ( i == 0 )
126             {
127               m_ADesc = I->ADesc;
128             }
129           else
130             {
131               if ( I->ADesc.AudioSamplingRate != m_ADesc.AudioSamplingRate )
132                 {
133                   DefaultLogSink().Error("AudioSamplingRate mismatch in PCM parser list.");
134                   return RESULT_FORMAT;
135                 }
136
137               if ( I->ADesc.QuantizationBits  != m_ADesc.QuantizationBits )
138                 {
139                   DefaultLogSink().Error("QuantizationBits mismatch in PCM parser list.");
140                   return RESULT_FORMAT;
141                 }
142
143               if ( I->ADesc.ContainerDuration < m_ADesc.ContainerDuration )
144                 m_ADesc.ContainerDuration = I->ADesc.ContainerDuration;
145
146               m_ADesc.BlockAlign += I->ADesc.BlockAlign;
147             }
148
149           m_ChannelCount += I->ADesc.ChannelCount;
150         }
151
152       if ( ASDCP_SUCCESS(result) )
153         result = I->FB.Capacity(PCM::CalcFrameBufferSize(m_ADesc));
154
155       if ( ASDCP_SUCCESS(result) )
156         push_back(I);
157     }
158
159   m_ADesc.ChannelCount = m_ChannelCount;
160   m_ADesc.AvgBps = m_ADesc.AvgBps * m_ChannelCount;
161
162   if ( ASDCP_FAILURE(result) )
163     clear();
164   
165   return result;
166 }
167
168 //
169 Result_t
170 ASDCP::PCMParserList::FillAudioDescriptor(PCM::AudioDescriptor& ADesc) const
171 {
172   ADesc = m_ADesc;
173   return RESULT_OK;
174 }
175
176 //
177 Result_t
178 ASDCP::PCMParserList::Reset()
179 {
180   Result_t result = RESULT_OK;
181   PCMParserList::iterator self_i;
182
183   for ( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result) ; self_i++ )
184     result = (*self_i)->Parser.Reset();
185
186   return result;
187 }
188
189
190 //
191 Result_t
192 ASDCP::PCMParserList::ReadFrame(PCM::FrameBuffer& OutFB)
193 {
194   Result_t result = RESULT_OK;
195
196   if ( size() == 1 )
197     return front()->Parser.ReadFrame(OutFB);
198
199   PCMParserList::iterator self_i;
200   assert(PCM::CalcFrameBufferSize(m_ADesc) <= OutFB.Capacity());
201
202   for ( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result) ; self_i++ )
203     result = (*self_i)->ReadFrame();
204
205   if ( ASDCP_SUCCESS(result) )
206     {
207       OutFB.Size(PCM::CalcFrameBufferSize(m_ADesc));
208
209       //      ui32_t sample_size = (PCM::CalcSampleSize(m_ADesc));
210       byte_t* Out_p = OutFB.Data();
211       byte_t* End_p = Out_p + OutFB.Size();
212
213       while ( Out_p < End_p && ASDCP_SUCCESS(result) )
214         {
215           self_i = begin();
216
217           while ( self_i != end() && ASDCP_SUCCESS(result) )
218             {
219               result = (*self_i)->PutSample(Out_p);
220               Out_p += (*self_i)->SampleSize();
221               self_i++;
222             }
223         }
224
225       assert(Out_p == End_p);
226     }
227
228   return result;
229 }
230
231 //
232 // end PCMParserList.cpp
233 //