1 /**
2 *
3 * Lame ACM wrapper, encode/decode MP3 based RIFF/AVI files in MS Windows
4 *
5 * Copyright (c) 2002 Steve Lhomme <steve.lhomme at free.fr>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23 /*!
24 \author Steve Lhomme
25 \version \$Id$
26 */
27
28 #if !defined(STRICT)
29 #define STRICT
30 #endif // STRICT
31
32 #include <assert.h>
33 #include <windows.h>
34
35 #ifdef ENABLE_DECODING
36
37 #include "adebug.h"
38
39 #include "DecodeStream.h"
40
41 // static methods
42
Create()43 DecodeStream * DecodeStream::Create()
44 {
45 DecodeStream * Result;
46
47 Result = new DecodeStream;
48
49 return Result;
50 }
51
Erase(const DecodeStream * a_ACMStream)52 const bool DecodeStream::Erase(const DecodeStream * a_ACMStream)
53 {
54 delete a_ACMStream;
55 return true;
56 }
57
58 // class methods
59
DecodeStream()60 DecodeStream::DecodeStream() :
61 m_WorkingBufferUseSize(0),
62 gfp(NULL)
63 {
64 /// \todo get the debug level from the registry
65 my_debug = new ADbg(DEBUG_LEVEL_CREATION);
66 if (my_debug != NULL) {
67 unsigned char DebugFileName[512];
68
69 my_debug->setPrefix("MPG123stream"); /// \todo get it from the registry
70 my_debug->setIncludeTime(true); /// \todo get it from the registry
71
72 // Check in the registry if we have to Output Debug information
73 DebugFileName[0] = '\0';
74
75 HKEY OssKey;
76 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\MUKOLI", 0, KEY_READ , &OssKey ) == ERROR_SUCCESS) {
77 DWORD DataType;
78 DWORD DebugFileNameSize = 512;
79 if (RegQueryValueEx( OssKey, "DebugFile", NULL, &DataType, DebugFileName, &DebugFileNameSize ) == ERROR_SUCCESS) {
80 if (DataType == REG_SZ) {
81 my_debug->setUseFile(true);
82 my_debug->setDebugFile((char *)DebugFileName);
83 my_debug->OutPut("Debug file is %s",(char *)DebugFileName);
84 }
85 }
86 }
87 my_debug->OutPut(DEBUG_LEVEL_FUNC_START, "DecodeStream Creation (0X%08X)",this);
88 }
89 else {
90 ADbg debug;
91 debug.OutPut("DecodeStream::ACMACMStream : Impossible to create my_debug");
92 }
93
94 }
95
~DecodeStream()96 DecodeStream::~DecodeStream()
97 {
98 // lame_close( gfp );
99
100 if (my_debug != NULL)
101 {
102 my_debug->OutPut(DEBUG_LEVEL_FUNC_START, "DecodeStream Deletion (0X%08X)",this);
103 delete my_debug;
104 }
105 }
106
init(const int nSamplesPerSec, const int nChannels, const int nAvgBytesPerSec, const int nSourceBitrate)107 bool DecodeStream::init(const int nSamplesPerSec, const int nChannels, const int nAvgBytesPerSec, const int nSourceBitrate)
108 {
109 bool bResult = false;
110
111 my_SamplesPerSec = nSamplesPerSec;
112 my_Channels = nChannels;
113 my_AvgBytesPerSec = nAvgBytesPerSec;
114 my_SourceBitrate = nSourceBitrate;
115
116 bResult = true;
117
118 return bResult;
119 }
120
open()121 bool DecodeStream::open()
122 {
123 bool bResult = false;
124
125 bResult = bool(InitMP3(&my_DecodeData) != 0);
126
127 return bResult;
128 }
129
close(LPBYTE pOutputBuffer, DWORD *pOutputSize)130 bool DecodeStream::close(LPBYTE pOutputBuffer, DWORD *pOutputSize)
131 {
132
133 bool bResult = false;
134 /*
135 int nOutputSamples = 0;
136
137 nOutputSamples = lame_encode_flush( gfp, pOutputBuffer, 0 );
138
139 if ( nOutputSamples < 0 )
140 {
141 // BUFFER_TOO_SMALL
142 *pOutputSize = 0;
143 }
144 else
145 {
146 *pOutputSize = nOutputSamples;
147
148 bResult = true;
149 }
150 /*
151 // lame will be close in VbrWriteTag function
152 if ( !lame_get_bWriteVbrTag( gfp ) )
153 {
154 // clean up of allocated memory
155 lame_close( gfp );
156 }
157 */
158
159 ExitMP3(&my_DecodeData);
160
161 bResult = true;
162
163 return bResult;
164 }
165
GetOutputSizeForInput(const DWORD the_SrcLength) const166 DWORD DecodeStream::GetOutputSizeForInput(const DWORD the_SrcLength) const
167 {
168 DWORD Result;
169
170 double OutputInputRatio = double(my_SamplesPerSec * 2 * my_Channels) / double(my_SourceBitrate);
171
172 OutputInputRatio *= 1.15; // allow 15% more
173
174 Result = DWORD(double(the_SrcLength) * OutputInputRatio);
175
176 my_debug->OutPut(DEBUG_LEVEL_FUNC_CODE, "Result = %d (OutputInputRatio = %f)",Result,OutputInputRatio);
177
178 return Result;
179 }
180
ConvertBuffer(LPACMDRVSTREAMHEADER a_StreamHeader)181 bool DecodeStream::ConvertBuffer(LPACMDRVSTREAMHEADER a_StreamHeader)
182 {
183 bool result = false;
184
185 if (my_debug != NULL)
186 {
187 my_debug->OutPut(DEBUG_LEVEL_FUNC_DEBUG, "enter DecodeStream::ConvertBuffer");
188 }
189
190 int ProcessedBytes;
191
192 int ret = decodeMP3(&my_DecodeData, a_StreamHeader->pbSrc, a_StreamHeader->cbSrcLength, (char *)a_StreamHeader->pbDst, a_StreamHeader->cbDstLength, &ProcessedBytes);
193
194 switch (ret)
195 {
196 case MP3_OK:
197 a_StreamHeader->cbSrcLengthUsed = a_StreamHeader->cbSrcLength;
198 a_StreamHeader->cbDstLengthUsed = ProcessedBytes;
199 result = true;
200 break;
201 case MP3_NEED_MORE:
202 a_StreamHeader->cbSrcLengthUsed = 0;
203 a_StreamHeader->cbDstLengthUsed = 0;
204 break;
205 case MP3_ERR:
206 break;
207 }
208
209 /*
210 DWORD InSize = a_StreamHeader->cbSrcLength / 2, OutSize = a_StreamHeader->cbDstLength; // 2 for 8<->16 bits
211
212 // Encode it
213 int dwSamples;
214 int nOutputSamples = 0;
215
216 dwSamples = InSize / lame_get_num_channels( gfp );
217
218 if ( 1 == lame_get_num_channels( gfp ) )
219 {
220 nOutputSamples = lame_encode_buffer(gfp,(PSHORT)a_StreamHeader->pbSrc,(PSHORT)a_StreamHeader->pbSrc,dwSamples,a_StreamHeader->pbDst,a_StreamHeader->cbDstLength);
221 }
222 else
223 {
224 nOutputSamples = lame_encode_buffer_interleaved(gfp,(PSHORT)a_StreamHeader->pbSrc,dwSamples,a_StreamHeader->pbDst,a_StreamHeader->cbDstLength);
225 }
226
227 a_StreamHeader->cbSrcLengthUsed = a_StreamHeader->cbSrcLength;
228 a_StreamHeader->cbDstLengthUsed = nOutputSamples;
229
230 result = a_StreamHeader->cbDstLengthUsed <= a_StreamHeader->cbDstLength;
231 */
232 my_debug->OutPut(DEBUG_LEVEL_FUNC_CODE, "UsedSize = %d / EncodedSize = %d, result = %d, ret = %s", a_StreamHeader->cbSrcLengthUsed, a_StreamHeader->cbDstLengthUsed, result,
233 (ret == MP3_OK)?"MP3_OK":(ret == MP3_NEED_MORE)?"MP3_NEED_MORE":"error");
234
235 if (my_debug != NULL)
236 {
237 my_debug->OutPut(DEBUG_LEVEL_FUNC_DEBUG, "DecodeStream::ConvertBuffer result = %d",result);
238 }
239
240 return result;
241 }
242 #endif // ENABLE_DECODING
243