|
1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 //FC Based on Cmp4parser |
|
21 |
|
22 |
|
23 // INCLUDE FILES |
|
24 #include <f32file.h> |
|
25 #include "mp4composer.h" |
|
26 #include "vedvideosettings.h" |
|
27 #include "vedavcedit.h" |
|
28 |
|
29 |
|
30 // ASSERTIONS |
|
31 //#define MPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CVideoProcessorImpl"), EInternalAssertionFailure)) |
|
32 |
|
33 |
|
34 // MACROS |
|
35 //#define ?macro ?macro_def |
|
36 |
|
37 #ifdef _DEBUG |
|
38 #include <e32svr.h> |
|
39 #define PRINT(x) RDebug::Print x; |
|
40 #else |
|
41 #define PRINT(x) |
|
42 #endif |
|
43 |
|
44 // LOCAL CONSTANTS AND MACROS |
|
45 |
|
46 const TUint KFreeDiskSpaceCounter = 10; // Interval when to find out real free disk space |
|
47 const TUint KMaxComposeBufferSize = 512000; // : Adjust buffer size dynamically |
|
48 |
|
49 #ifdef _DEBUG |
|
50 const TInt KLeaveCode = CComposer::EComposerFailure; |
|
51 #else |
|
52 const TInt KLeaveCode = KErrGeneral; |
|
53 #endif |
|
54 |
|
55 // ============================= LOCAL FUNCTIONS =============================== |
|
56 |
|
57 // ----------------------------------------------------------------------------- |
|
58 // RateIndex: converts sample rate to rate index used in decoder config info |
|
59 // ----------------------------------------------------------------------------- |
|
60 // |
|
61 static TUint8 RateIndex(TInt aRate) |
|
62 { |
|
63 switch ( aRate ) |
|
64 { |
|
65 case 96000: |
|
66 return 0x0; |
|
67 case 88200: |
|
68 return 0x1; |
|
69 case 64000: |
|
70 return 0x2; |
|
71 case 48000: |
|
72 return 0x3; |
|
73 case 44100: |
|
74 return 0x4; |
|
75 case 32000: |
|
76 return 0x5; |
|
77 case 24000: |
|
78 return 0x6; |
|
79 case 22050: |
|
80 return 0x7; |
|
81 case 16000: |
|
82 return 0x8; |
|
83 case 12000: |
|
84 return 0x9; |
|
85 case 11025: |
|
86 return 0xa; |
|
87 case 8000: |
|
88 return 0xb; |
|
89 case 7350: |
|
90 return 0xc; |
|
91 default: |
|
92 return 0xf; |
|
93 } |
|
94 } |
|
95 |
|
96 |
|
97 // ================= MEMBER FUNCTIONS ======================= |
|
98 |
|
99 // C++ default constructor can NOT contain any code, that |
|
100 // might leave. |
|
101 // |
|
102 |
|
103 CMP4Composer::CMP4Composer() |
|
104 { |
|
105 iMP4Handle = 0; |
|
106 iFreeDiskSpace = 0; |
|
107 iFreeDiskSpaceCounter = 0; |
|
108 iFirstWrite = ETrue; |
|
109 iFsOpened = EFalse; |
|
110 } |
|
111 |
|
112 // Two-phased constructor. |
|
113 CMP4Composer* CMP4Composer::NewL(const TDesC &aFileName, |
|
114 CParser::TVideoFormat aVideoFormat, |
|
115 CParser::TAudioFormat aAudioFormat, |
|
116 CVedAVCEdit *aAvcEdit) |
|
117 { |
|
118 CMP4Composer *self = new (ELeave) CMP4Composer; |
|
119 CleanupStack::PushL(self); |
|
120 self->ConstructL(aFileName, aVideoFormat, aAudioFormat, aAvcEdit); |
|
121 CleanupStack::Pop(); // self |
|
122 return self; |
|
123 } |
|
124 |
|
125 CMP4Composer* CMP4Composer::NewL(RFile* aFileHandle, |
|
126 CParser::TVideoFormat aVideoFormat, |
|
127 CParser::TAudioFormat aAudioFormat, |
|
128 CVedAVCEdit *aAvcEdit) |
|
129 { |
|
130 CMP4Composer *self = new (ELeave) CMP4Composer; |
|
131 CleanupStack::PushL(self); |
|
132 self->ConstructL(aFileHandle, aVideoFormat, aAudioFormat, aAvcEdit); |
|
133 CleanupStack::Pop(); // self |
|
134 return self; |
|
135 } |
|
136 |
|
137 // Symbian OS default constructor can leave. |
|
138 void CMP4Composer::ConstructL(const TDesC &aFileName, |
|
139 CParser::TVideoFormat aVideoFormat, |
|
140 CParser::TAudioFormat aAudioFormat, |
|
141 CVedAVCEdit *aAvcEdit) |
|
142 { |
|
143 TUint mediaType = 0; |
|
144 |
|
145 iOutputMovieFileName = TFileName(aFileName); |
|
146 iFileHandle = NULL; |
|
147 |
|
148 iAvcEdit = aAvcEdit; |
|
149 |
|
150 // open MP4 library |
|
151 |
|
152 TBuf<258> temp(aFileName); |
|
153 temp.ZeroTerminate(); |
|
154 |
|
155 MP4FileName name = reinterpret_cast<MP4FileName>( const_cast<TUint16*>(temp.Ptr()) ); |
|
156 |
|
157 SetMediaOptions(aVideoFormat, aAudioFormat, mediaType); |
|
158 |
|
159 MP4Err error; |
|
160 |
|
161 // if the filename length is greater 0, then compose to file else buffer |
|
162 if(aFileName.Length() > 0) |
|
163 { |
|
164 error = MP4ComposeOpen(&iMP4Handle, name, mediaType); |
|
165 } |
|
166 else |
|
167 { |
|
168 // initialize to compose to buffer |
|
169 iComposeBuffer = (TUint8*)HBufC::NewL( KMaxComposeBufferSize ); |
|
170 iComposedSize = KMaxComposeBufferSize; |
|
171 error = MP4ComposeOpenToBuffer(&iMP4Handle, mediaType,(mp4_u8*)iComposeBuffer,&iComposedSize); |
|
172 } |
|
173 |
|
174 if ( error != MP4_OK ) |
|
175 User::Leave(KLeaveCode); |
|
176 |
|
177 SetComposerOptionsL(aVideoFormat, aAudioFormat); |
|
178 |
|
179 } |
|
180 |
|
181 void CMP4Composer::ConstructL(RFile* aFileHandle, |
|
182 CParser::TVideoFormat aVideoFormat, |
|
183 CParser::TAudioFormat aAudioFormat, |
|
184 CVedAVCEdit *aAvcEdit) |
|
185 { |
|
186 TUint mediaType = 0; |
|
187 |
|
188 iOutputMovieFileName.Zero(); |
|
189 iFileHandle = aFileHandle; |
|
190 |
|
191 iAvcEdit = aAvcEdit; |
|
192 |
|
193 SetMediaOptions(aVideoFormat, aAudioFormat, mediaType); |
|
194 |
|
195 // open MP4 library |
|
196 MP4Err error; |
|
197 |
|
198 error = MP4ComposeOpenFileHandle(&iMP4Handle, aFileHandle, EDriveC, mediaType); |
|
199 |
|
200 if ( error != MP4_OK ) |
|
201 User::Leave(KLeaveCode); |
|
202 |
|
203 SetComposerOptionsL(aVideoFormat, aAudioFormat); |
|
204 |
|
205 } |
|
206 |
|
207 |
|
208 void CMP4Composer::SetMediaOptions(CParser::TVideoFormat aVideoFormat, |
|
209 CParser::TAudioFormat aAudioFormat, |
|
210 TUint& aMediaFlags) |
|
211 |
|
212 { |
|
213 |
|
214 if ( (aVideoFormat == CParser::EVideoFormatH263Profile0Level10) || |
|
215 (aVideoFormat == CParser::EVideoFormatH263Profile0Level45) ) |
|
216 { |
|
217 aMediaFlags = MP4_TYPE_H263_PROFILE_0; |
|
218 iVideoType = MP4_TYPE_H263_PROFILE_0; |
|
219 } |
|
220 |
|
221 #ifdef VIDEOEDITORENGINE_AVC_EDITING |
|
222 else if (aVideoFormat == CParser::EVideoFormatAVCProfileBaseline) |
|
223 { |
|
224 aMediaFlags = MP4_TYPE_AVC_PROFILE_BASELINE; |
|
225 iVideoType = MP4_TYPE_AVC_PROFILE_BASELINE; |
|
226 } |
|
227 #endif |
|
228 else |
|
229 { |
|
230 aMediaFlags = MP4_TYPE_MPEG4_VIDEO; |
|
231 iVideoType = MP4_TYPE_MPEG4_VIDEO; |
|
232 } |
|
233 |
|
234 if ( aAudioFormat == CParser::EAudioFormatAMR ) |
|
235 { |
|
236 aMediaFlags |= MP4_TYPE_AMR_NB; |
|
237 iAudioType = MP4_TYPE_AMR_NB; |
|
238 } |
|
239 |
|
240 else if ( aAudioFormat == CParser::EAudioFormatAAC ) |
|
241 { |
|
242 aMediaFlags |= MP4_TYPE_MPEG4_AUDIO; // added for AAC support. |
|
243 iAudioType = MP4_TYPE_MPEG4_AUDIO; |
|
244 } |
|
245 |
|
246 } |
|
247 |
|
248 void CMP4Composer::SetComposerOptionsL(CParser::TVideoFormat aVideoFormat, |
|
249 CParser::TAudioFormat aAudioFormat) |
|
250 { |
|
251 |
|
252 MP4Err error; |
|
253 |
|
254 TBool videoMpeg4OrAvc = ( aVideoFormat == CParser::EVideoFormatMPEG4 || |
|
255 aVideoFormat == CParser::EVideoFormatAVCProfileBaseline ); |
|
256 |
|
257 mp4_u32 flags = 0; |
|
258 flags |= MP4_FLAG_LARGEFILEBUFFER; // Note: What does this do when using RFile ? |
|
259 flags |= MP4_FLAG_METADATALAST; |
|
260 |
|
261 // generate MP4 file format if MPEG-4/AVC video & AAC audio |
|
262 if ( (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatAAC) || |
|
263 (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatNone) || |
|
264 (aVideoFormat == CParser::EVideoFormatNone && aAudioFormat == CParser::EAudioFormatAAC) ) |
|
265 { |
|
266 flags |= MP4_FLAG_GENERATE_MP4; |
|
267 } |
|
268 |
|
269 error = MP4ComposeSetFlags(iMP4Handle, flags); |
|
270 |
|
271 if (error != MP4_OK) |
|
272 if (error == MP4_OUT_OF_MEMORY) |
|
273 { |
|
274 User::LeaveNoMemory(); |
|
275 } |
|
276 else |
|
277 { |
|
278 User::Leave(KLeaveCode); |
|
279 } |
|
280 |
|
281 // set buffer sizes; only composer buffer settings are effective for this instance |
|
282 error = MP4SetCustomFileBufferSizes(iMP4Handle, K3gpMp4ComposerWriteBufferSize, K3gpMp4ComposerNrOfWriteBuffers, K3gpMp4ParserReadBufferSize ); |
|
283 |
|
284 if (error == MP4_OUT_OF_MEMORY) |
|
285 { |
|
286 User::Leave(KErrNoMemory); |
|
287 } |
|
288 else if ( error != MP4_OK ) |
|
289 { |
|
290 User::Leave(KLeaveCode); |
|
291 } |
|
292 } |
|
293 |
|
294 |
|
295 // Destructor |
|
296 CMP4Composer::~CMP4Composer() |
|
297 { |
|
298 if (iMP4Handle) |
|
299 { |
|
300 MP4ComposeClose(iMP4Handle); |
|
301 } |
|
302 |
|
303 if(iComposeBuffer) // added for Buffer support |
|
304 { |
|
305 User::Free(iComposeBuffer); |
|
306 iComposeBuffer=0; |
|
307 } |
|
308 |
|
309 iMP4Handle = 0; |
|
310 |
|
311 if (iFsOpened) |
|
312 { |
|
313 iFS.Close(); |
|
314 iFsOpened = EFalse; |
|
315 } |
|
316 |
|
317 |
|
318 } |
|
319 |
|
320 // --------------------------------------------------------- |
|
321 // CMP4Composer::WriteFrames |
|
322 // Write the next frame(s) to file |
|
323 // --------------------------------------------------------- |
|
324 // |
|
325 TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize, |
|
326 TInt aDuration, TInt aKeyFrame, |
|
327 TInt aNumberOfFrames, TInt aFrameType) |
|
328 { |
|
329 MP4Err error = KErrNone; |
|
330 |
|
331 // get the parameters |
|
332 TUint32 frameSize = aFrameSize; |
|
333 TUint32 duration = aDuration; |
|
334 mp4_bool keyframe = (mp4_bool)aKeyFrame; |
|
335 TInt numberOfFrames = aNumberOfFrames; |
|
336 TFrameType frameType = (aFrameType>0 ? (aFrameType==1 ? EFrameTypeAudio : EFrameTypeVideo) |
|
337 : EFrameTypeNone); |
|
338 |
|
339 if (frameType == EFrameTypeVideo) |
|
340 { |
|
341 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(aSrcBuffer.Ptr()), |
|
342 frameSize, duration, keyframe); |
|
343 if ( error != MP4_OK ) |
|
344 return KLeaveCode; |
|
345 } |
|
346 |
|
347 else if (frameType == EFrameTypeAudio) |
|
348 { |
|
349 error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(aSrcBuffer.Ptr()), |
|
350 frameSize, numberOfFrames, duration); |
|
351 if ( error != MP4_OK ) |
|
352 return KLeaveCode; |
|
353 } |
|
354 else |
|
355 User::Panic(_L("CMovieProcessorImpl"), EComposerFailure); |
|
356 |
|
357 return KErrNone; |
|
358 |
|
359 } |
|
360 |
|
361 |
|
362 TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize, |
|
363 TInt aDuration, TInt aKeyFrame, |
|
364 TInt aNumberOfFrames, TInt aFrameType, |
|
365 TInt& aMP4Size, TBool aModeChanged, |
|
366 TBool aFirstFrameOfClip, TInt aMode, TBool /*aFromEncoder*/) |
|
367 { |
|
368 MP4Err error = KErrNone; |
|
369 |
|
370 // get the parameters |
|
371 TUint32 frameSize = aFrameSize; |
|
372 TUint32 duration = aDuration; |
|
373 mp4_bool keyframe = ( aKeyFrame ) ? ETrue : EFalse; |
|
374 TInt numberOfFrames = aNumberOfFrames; |
|
375 TFrameType frameType = (aFrameType > 0 ? (aFrameType == 1 ? EFrameTypeAudio : EFrameTypeVideo) |
|
376 : EFrameTypeNone); |
|
377 TUint8* dataPtr = (TUint8*)(aSrcBuffer.Ptr()); |
|
378 TInt tmpSize = 0; |
|
379 |
|
380 // call this only for the first frame of every clip |
|
381 if ( aFirstFrameOfClip && (iVideoType == MP4_TYPE_MPEG4_VIDEO) && (aMP4Size == 0)) |
|
382 { |
|
383 if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0) |
|
384 aMP4Size = tmpSize; //This will be the new Mp4Size as it will be consider and since by reference it is maintained |
|
385 } |
|
386 |
|
387 if (frameType == EFrameTypeVideo) |
|
388 { |
|
389 if ( iVideoType == MP4_TYPE_MPEG4_VIDEO ) |
|
390 { |
|
391 if ( iFirstWrite ) |
|
392 { |
|
393 // VOS |
|
394 error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle, |
|
395 (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), aMP4Size ); |
|
396 iFirstWrite = EFalse; |
|
397 |
|
398 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size), |
|
399 ( frameSize - aMP4Size ), duration, keyframe); |
|
400 } |
|
401 else |
|
402 { |
|
403 // for MPEG4 - check the first 32 bits to make sure we don't |
|
404 // have VOS pre-pended to VOP data |
|
405 if (dataPtr[0] == 0x00 && dataPtr[1] == 0x00 && dataPtr[2] == 0x01 && dataPtr[3] == 0xb0) |
|
406 { // since intermediate Vos set to proper value |
|
407 // Not Short Header may have User Data space problem with PSC |
|
408 if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0) |
|
409 aMP4Size = tmpSize; //This will be the new Mp4Size as it will be considered |
|
410 dataPtr += aMP4Size; |
|
411 frameSize -= aMP4Size; |
|
412 } |
|
413 |
|
414 if (frameSize == 0) |
|
415 return KErrWrite; |
|
416 |
|
417 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr), |
|
418 frameSize, duration, keyframe); |
|
419 } |
|
420 } |
|
421 |
|
422 #ifdef VIDEOEDITORENGINE_AVC_EDITING |
|
423 else if ( iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE ) |
|
424 { |
|
425 |
|
426 if ( iFirstWrite || aFirstFrameOfClip) |
|
427 { |
|
428 if(iFirstWrite) |
|
429 { |
|
430 iFrameNumber = 0; |
|
431 iFirstWrite = EFalse; |
|
432 } |
|
433 |
|
434 aMP4Size = 0; |
|
435 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size), |
|
436 ( frameSize - aMP4Size ), duration, keyframe); |
|
437 } |
|
438 else |
|
439 { |
|
440 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr), |
|
441 frameSize, duration, keyframe); |
|
442 } |
|
443 |
|
444 iFrameNumber++; |
|
445 } |
|
446 #endif |
|
447 |
|
448 else // H.263 |
|
449 { |
|
450 error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), |
|
451 frameSize, duration, keyframe); |
|
452 |
|
453 } |
|
454 if ( error != MP4_OK ) |
|
455 return KLeaveCode; |
|
456 } |
|
457 else if (frameType == EFrameTypeAudio) |
|
458 { |
|
459 error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), |
|
460 frameSize, numberOfFrames, duration); |
|
461 if ( error != MP4_OK ) |
|
462 return KLeaveCode; |
|
463 } |
|
464 else |
|
465 User::Panic(_L("CMovieProcessorImpl"), EComposerFailure); |
|
466 |
|
467 return KErrNone; |
|
468 } |
|
469 |
|
470 |
|
471 |
|
472 // --------------------------------------------------------- |
|
473 // CMP4Composer::ComposeHeaderL |
|
474 // Get relevant stream parameters by calling mp4 library functions |
|
475 // (other items were commented in a header). |
|
476 // --------------------------------------------------------- |
|
477 // |
|
478 |
|
479 |
|
480 void CMP4Composer::ComposeHeaderL(CComposer::TStreamParameters& aStreamParameters, TInt aOutputVideoTimeScale, |
|
481 TInt aOutputAudioTimeScale, TInt aAudioFramesInSample) |
|
482 { |
|
483 MP4Err iError=KErrNone; |
|
484 |
|
485 TInt width = aStreamParameters.iVideoWidth; |
|
486 TInt height = aStreamParameters.iVideoHeight; |
|
487 TInt avgbitrate = aStreamParameters.iStreamBitrate; |
|
488 TInt maxbitrate = avgbitrate; |
|
489 TInt audioFramesPerSample = aAudioFramesInSample;//aStreamParameters.iAudioFramesInSample; |
|
490 TInt audioTimescale = aOutputAudioTimeScale; |
|
491 TInt modeSet=0x8180; |
|
492 |
|
493 if(iAudioType == MP4_TYPE_MPEG4_AUDIO) // added for AAC support |
|
494 { |
|
495 // reset for AAC audio according to the code sent for AAC support. |
|
496 audioFramesPerSample = 0; |
|
497 modeSet = 0; |
|
498 } |
|
499 |
|
500 // set this to first clip's time scale |
|
501 TInt timescale = aOutputVideoTimeScale; |
|
502 |
|
503 iError = MP4ComposeAddAudioDescription(iMP4Handle,(mp4_u32)audioTimescale, |
|
504 (mp4_u8)audioFramesPerSample,(mp4_u16)modeSet); |
|
505 if (iError != MP4_OK) |
|
506 User::Leave(KLeaveCode); |
|
507 |
|
508 // write video description |
|
509 iError = MP4ComposeAddVideoDescription(iMP4Handle,(mp4_u32)timescale, |
|
510 (mp4_u16)width,(mp4_u16)height,(mp4_u32)maxbitrate,(mp4_u32)avgbitrate); |
|
511 |
|
512 if (iError != MP4_OK) |
|
513 User::Leave(KLeaveCode); |
|
514 |
|
515 if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level10 ) |
|
516 { |
|
517 TVideoClipProperties prop; |
|
518 prop.iH263Level = 10; |
|
519 MP4ComposeSetVideoClipProperties(iMP4Handle, prop); |
|
520 } |
|
521 |
|
522 else if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level45 ) |
|
523 { |
|
524 TVideoClipProperties prop; |
|
525 prop.iH263Level = 45; |
|
526 MP4ComposeSetVideoClipProperties(iMP4Handle, prop); |
|
527 } |
|
528 |
|
529 if (!iFsOpened) // Check if file server is open already |
|
530 { |
|
531 User::LeaveIfError(iFS.Connect()); |
|
532 iFsOpened = ETrue; |
|
533 } |
|
534 |
|
535 if (iFileHandle == 0) |
|
536 { |
|
537 // get target drive number |
|
538 TParse fp; |
|
539 User::LeaveIfError(iFS.Parse(iOutputMovieFileName, fp)); |
|
540 TPtrC driveletter = fp.Drive(); |
|
541 TChar drl = driveletter[0]; |
|
542 User::LeaveIfError(RFs::CharToDrive(drl, iDriveNumber)); |
|
543 } |
|
544 else |
|
545 { |
|
546 // get target drive number |
|
547 TDriveInfo info; |
|
548 TInt error = iFileHandle->Drive(iDriveNumber, info); |
|
549 } |
|
550 } |
|
551 |
|
552 // ----------------------------------------------------------------------------- |
|
553 // CMP4Composer::DriveFreeSpaceL |
|
554 // Calculate free space on a drive in bytes. |
|
555 // (other items were commented in a header). |
|
556 // ----------------------------------------------------------------------------- |
|
557 // |
|
558 TInt64 CMP4Composer::DriveFreeSpaceL() |
|
559 { |
|
560 TVolumeInfo volumeinfo; |
|
561 |
|
562 if (iFreeDiskSpaceCounter % KFreeDiskSpaceCounter == 0) |
|
563 { |
|
564 User::LeaveIfError(iFS.Volume(volumeinfo, iDriveNumber)); |
|
565 iFreeDiskSpace = volumeinfo.iFree; |
|
566 } |
|
567 |
|
568 iFreeDiskSpaceCounter++; |
|
569 return iFreeDiskSpace; |
|
570 |
|
571 } |
|
572 |
|
573 // ----------------------------------------------------------------------------- |
|
574 // CMP4Composer::GetComposedBuffer New Function added for Buffer support |
|
575 // Gets the Composed buffer from the composer |
|
576 // (other items were commented in a header). |
|
577 // ----------------------------------------------------------------------------- |
|
578 // |
|
579 TUint8* CMP4Composer::GetComposedBuffer() |
|
580 { |
|
581 return iComposeBuffer; |
|
582 } |
|
583 |
|
584 // ----------------------------------------------------------------------------- |
|
585 // CMP4Composer::GetComposedBufferSize New Function added for Buffer support |
|
586 // Gets the Composed buffer size from the composer |
|
587 // (other items were commented in a header). |
|
588 // ----------------------------------------------------------------------------- |
|
589 // |
|
590 TUint CMP4Composer::GetComposedBufferSize() |
|
591 { |
|
592 return iComposedSize; |
|
593 } |
|
594 |
|
595 // --------------------------------------------------------- |
|
596 // CMP4Composer::Close |
|
597 // Closes the composer instance & creates the output 3gp file |
|
598 // (other items were commented in a header). |
|
599 // --------------------------------------------------------- |
|
600 // |
|
601 TInt CMP4Composer::Close() |
|
602 { |
|
603 |
|
604 #ifdef VIDEOEDITORENGINE_AVC_EDITING |
|
605 |
|
606 if (iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE) |
|
607 { |
|
608 HBufC8* AVCDCR = NULL; |
|
609 TInt error; |
|
610 |
|
611 TRAP(error, AVCDCR = (HBufC8*) HBufC8::NewL(16384)); |
|
612 if (error != KErrNone) |
|
613 return error; |
|
614 |
|
615 TPtr8 ptr = AVCDCR->Des(); |
|
616 |
|
617 // Construct AVC Decoder Configuration Record from the SPS / PPS sets |
|
618 TRAP(error, iAvcEdit->ConstructAVCDecoderConfigurationRecordL(ptr)); |
|
619 if (error != KErrNone) |
|
620 { |
|
621 delete AVCDCR; |
|
622 return error; |
|
623 } |
|
624 |
|
625 // Pass the AVC Decoder Configuration Record to the 3GPMP4 library |
|
626 MP4Err mp4Error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle, |
|
627 (mp4_u8*)(ptr.Ptr()), ptr.Length()); |
|
628 |
|
629 delete AVCDCR; |
|
630 |
|
631 if (mp4Error != MP4_OK) |
|
632 return EComposerFailure; |
|
633 } |
|
634 |
|
635 #endif |
|
636 |
|
637 MP4Err error = MP4ComposeClose(iMP4Handle); |
|
638 |
|
639 iMP4Handle = 0; |
|
640 |
|
641 if (error != MP4_OK) |
|
642 return EComposerFailure; |
|
643 |
|
644 if (iFsOpened) |
|
645 { |
|
646 iFS.Close(); |
|
647 iFsOpened = EFalse; |
|
648 } |
|
649 |
|
650 return KErrNone; |
|
651 } |
|
652 |
|
653 |
|
654 // ----------------------------------------------------------------------------- |
|
655 // CMP4Composer::GetMp4SpecificSize |
|
656 // Gets the length of MPEG-4 decoder specific info in aSrcBuf |
|
657 // (other items were commented in a header). |
|
658 // ----------------------------------------------------------------------------- |
|
659 // |
|
660 TInt CMP4Composer::GetMp4SpecificSize(TDesC8& aSrcBuf,TBool aModeChange,TInt aStreamMode) |
|
661 { |
|
662 TUint8* dtPtr = (TUint8*)(aSrcBuf.Ptr()); |
|
663 TInt mp4size =0; |
|
664 TInt bufSize; |
|
665 TInt flag; |
|
666 |
|
667 if (!aModeChange && (aStreamMode == 2)) //2 indicates short header in VedCommon |
|
668 { |
|
669 bufSize = aSrcBuf.Size()-3; |
|
670 for(TInt i=0;i<bufSize;i++) |
|
671 { |
|
672 flag = (dtPtr[i+2]>>2)<<2; |
|
673 if (dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && flag == 0x80) // user data ???????????? |
|
674 { |
|
675 mp4size=i; |
|
676 break; |
|
677 } |
|
678 } |
|
679 } |
|
680 else |
|
681 { |
|
682 bufSize = aSrcBuf.Size()-4; |
|
683 for(TInt i=0;i<bufSize;i++) |
|
684 { |
|
685 if ((dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && dtPtr[i+2] == 0x01 && dtPtr[i+3] == 0xb3) || |
|
686 (dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && dtPtr[i+2] == 0x01 && dtPtr[i+3] == 0xb6)) |
|
687 { |
|
688 mp4size=i; |
|
689 break; |
|
690 } |
|
691 } |
|
692 } |
|
693 |
|
694 // MP4 specific size will be zero, if there is a GOV or VOP header in the |
|
695 // very beginning of the buffer |
|
696 |
|
697 return mp4size; |
|
698 } |
|
699 |
|
700 |
|
701 // --------------------------------------------------------- |
|
702 // CMP4Composer::WriteAudioSpecificInfo |
|
703 // Writes the Audio decoder Specific info required in case of AAC |
|
704 // Decoder specific info is provided externally |
|
705 // (other items were commented in a header). |
|
706 // decoder info is provided externally |
|
707 // --------------------------------------------------------- |
|
708 // |
|
709 // added to Support AAC audio files |
|
710 TInt CMP4Composer::WriteAudioSpecificInfo(HBufC8*& aSrcBuf) |
|
711 { |
|
712 TInt error = KErrNone; |
|
713 mp4_u8* aSrcB = const_cast<mp4_u8*>(aSrcBuf->Ptr()); |
|
714 error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, aSrcB, aSrcBuf->Size()); |
|
715 |
|
716 if (error != MP4_OK) |
|
717 return KErrGeneral; |
|
718 |
|
719 return KErrNone; |
|
720 } |
|
721 |
|
722 // --------------------------------------------------------- |
|
723 // CMP4Composer::WriteAudioSpecificInfo |
|
724 // Writes the Audio decoder Specific info required in case of AAC |
|
725 // Decoder specific info is derived from samplerate and # of channels |
|
726 // (other items were commented in a header). |
|
727 // --------------------------------------------------------- |
|
728 // |
|
729 // added to Support AAC audio files |
|
730 TInt CMP4Composer::WriteAudioSpecificInfo(TInt aSampleRate, TInt aNumChannels) |
|
731 { |
|
732 TInt error = KErrNone; |
|
733 |
|
734 TUint8 data[2]; |
|
735 |
|
736 data[0] = 2<<3; // AAC-LC |
|
737 TUint8 rate = RateIndex(aSampleRate); |
|
738 data[0] |= rate>>1; |
|
739 data[1] = TUint8(rate<<7); |
|
740 data[1] |= TUint8(aNumChannels<<3); |
|
741 |
|
742 error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, data, 2); |
|
743 |
|
744 if (error != MP4_OK) |
|
745 return KErrGeneral; |
|
746 |
|
747 return KErrNone; |
|
748 } |
|
749 |
|
750 |
|
751 // ----------------------------------------------------------------------------- |
|
752 // CMP4Composer::GetAVCDecoderSpecificInfoSize |
|
753 // Gets the length of AVC decoder specific info in aSrcBuf |
|
754 // (other items were commented in a header). |
|
755 // ----------------------------------------------------------------------------- |
|
756 // |
|
757 TInt CMP4Composer::GetAVCDecoderSpecificInfoSize(TDesC8& aSrcBuf) |
|
758 { |
|
759 TUint8* srcPtr = (TUint8*)(aSrcBuf.Ptr()); |
|
760 TInt skip = 0; |
|
761 // TInt error = KErrNone; |
|
762 |
|
763 // skip 4 bytes for |
|
764 // configVersion, profile, profile compatibility and Level |
|
765 skip += 4; |
|
766 |
|
767 // skip 1 bytes for lengthSizeMinusOne |
|
768 skip += 1; |
|
769 |
|
770 // skip 1 bytes for num of seq Param sets |
|
771 TInt numOfSSP = 0x1F & srcPtr[skip]; |
|
772 skip += 1; |
|
773 |
|
774 for (TInt i = 0; i < numOfSSP; i++) |
|
775 { |
|
776 TInt sspSize = srcPtr[skip]*256 + srcPtr[skip+1]; |
|
777 skip += 2; |
|
778 skip += sspSize; |
|
779 } |
|
780 |
|
781 TInt numOfPSP = srcPtr[skip]; |
|
782 skip += 1; |
|
783 |
|
784 for (TInt i = 0; i < numOfPSP; i++) |
|
785 { |
|
786 TInt pspSize = srcPtr[skip]*256 + srcPtr[skip+1]; |
|
787 skip += 2; |
|
788 skip += pspSize; |
|
789 } |
|
790 |
|
791 return skip; |
|
792 } |
|
793 |
|
794 |
|
795 |
|
796 // End of File |