mmplugins/lib3gp/impl/src/mp4parse.cpp
changeset 0 40261b775718
child 11 d5f04de580b7
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <3gplibrary/mp4config.h>
       
    17 #include <3gplibrary/mp4lib.h>
       
    18 #include "mp4atom.h"
       
    19 #include "mp4memwrap.h"
       
    20 #include "mp4file.h"
       
    21 #include "mp4buffer.h"
       
    22 #include "mp4endian.h"
       
    23 #include "mp4utils.h"
       
    24 
       
    25 using namespace ContentAccess;
       
    26 
       
    27 extern EXPORT_C MP4Err MP4ParseOpen(MP4Handle *apihandle,
       
    28                                                  MP4FileName filename)
       
    29 {
       
    30   MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
       
    31   *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
       
    32   if (*handle == NULL)
       
    33     return MP4_OUT_OF_MEMORY;
       
    34 
       
    35   (*handle)->file32Duplicate = NULL;
       
    36   (*handle)->FileHandleFromOutside = EFalse;
       
    37   (*handle)->sourceType = MP4_SOURCE_RFILE;
       
    38 
       
    39   if (filename)
       
    40     if (initFileRead(filename, *handle) == -1)
       
    41     {
       
    42       closeFile(*handle);
       
    43       mp4free(*handle);
       
    44       *handle = NULL;
       
    45       return MP4_FILE_ERROR;
       
    46     }
       
    47 
       
    48   (*handle)->mem = listCreate();
       
    49   if ((*handle)->mem == NULL)
       
    50   {
       
    51     closeFile(*handle);
       
    52     mp4free(*handle);
       
    53     *handle = NULL;
       
    54     return MP4_OUT_OF_MEMORY;
       
    55   }
       
    56 
       
    57   if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
       
    58   {
       
    59     listDestroyList((*handle)->mem);
       
    60     closeFile(*handle);
       
    61     mp4free(*handle);
       
    62     *handle = NULL;
       
    63     return MP4_OUT_OF_MEMORY;
       
    64   }
       
    65 
       
    66   if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
       
    67   {
       
    68     mp4free((*handle)->buf);
       
    69     listDestroyList((*handle)->mem);
       
    70     closeFile(*handle);
       
    71     mp4free(*handle);
       
    72     *handle = NULL;
       
    73     return MP4_OUT_OF_MEMORY;
       
    74   }
       
    75 
       
    76   // register for stblib use 
       
    77   if (openStdlib() !=  MP4_OK)
       
    78 	  {
       
    79 	  mp4free((*handle)->diskReadBuf);	  
       
    80 	  mp4free((*handle)->buf);
       
    81 	  listDestroyList((*handle)->mem);
       
    82 	  closeFile(*handle);
       
    83 	  mp4free(*handle);
       
    84 	  *handle = NULL;
       
    85 	  
       
    86 	  return MP4_ERROR;
       
    87 	  }
       
    88   
       
    89   return MP4_OK;
       
    90 }
       
    91 
       
    92 extern EXPORT_C MP4Err MP4ParseOpenFileHandle(MP4Handle *apihandle,
       
    93                                                  RFile *inputfile)
       
    94 {
       
    95   MP4Err err;
       
    96   RFile64 *f64 = new RFile64;
       
    97   if (f64 == NULL)
       
    98   {
       
    99     return MP4_OUT_OF_MEMORY;
       
   100   }
       
   101   if  (f64->Duplicate(*inputfile) != KErrNone)
       
   102   {
       
   103     delete f64;
       
   104     return MP4_ERROR;
       
   105   }
       
   106   err = MP4ParseOpenFileHandle64(apihandle, f64);
       
   107   if (err == MP4_OK)
       
   108   {    
       
   109     MP4HandleImp* handle = (MP4HandleStruct **)apihandle;
       
   110     (*handle)->file32Duplicate = (void*)(f64);
       
   111   }
       
   112   return err;
       
   113 }
       
   114 
       
   115 extern EXPORT_C MP4Err MP4ParseOpenFileHandle64(MP4Handle *apihandle,
       
   116                                                  RFile64 *inputfile)
       
   117 {
       
   118   MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
       
   119   *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
       
   120   if (*handle == NULL)
       
   121     return MP4_OUT_OF_MEMORY;
       
   122 
       
   123   (*handle)->file32Duplicate = NULL;
       
   124   (*handle)->rfile = (void *)inputfile;
       
   125   (*handle)->file = (*handle)->rfile;
       
   126   (*handle)->FileHandleFromOutside = ETrue;
       
   127   (*handle)->sourceType = MP4_SOURCE_RFILE;
       
   128   if (inputfile == NULL)
       
   129       {
       
   130       closeFile(*handle);
       
   131       mp4free(*handle);
       
   132       *handle = NULL;
       
   133       return MP4_FILE_ERROR;
       
   134       }
       
   135 
       
   136   (*handle)->mem = listCreate();
       
   137   if ((*handle)->mem == NULL)
       
   138   {
       
   139     closeFile(*handle);
       
   140     mp4free(*handle);
       
   141     *handle = NULL;
       
   142     return MP4_OUT_OF_MEMORY;
       
   143   }
       
   144 
       
   145   if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
       
   146   {
       
   147     listDestroyList((*handle)->mem);
       
   148     closeFile(*handle);
       
   149     mp4free(*handle);
       
   150     *handle = NULL;
       
   151     return MP4_OUT_OF_MEMORY;
       
   152   }
       
   153 
       
   154   if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
       
   155   {
       
   156     mp4free((*handle)->buf);
       
   157     listDestroyList((*handle)->mem);
       
   158     closeFile(*handle);
       
   159     mp4free(*handle);
       
   160     *handle = NULL;
       
   161     return MP4_OUT_OF_MEMORY;
       
   162   }
       
   163 
       
   164   	// register for stblib use 
       
   165   	if (openStdlib() !=  MP4_OK)
       
   166   		{
       
   167   		// clean up
       
   168   		mp4free((*handle)->diskReadBuf);
       
   169 		mp4free((*handle)->buf);
       
   170 		listDestroyList((*handle)->mem);
       
   171 		closeFile(*handle);
       
   172 		mp4free(*handle);
       
   173 		*handle = NULL;
       
   174   
       
   175 		return MP4_ERROR;
       
   176   		} 
       
   177   
       
   178   return MP4_OK;
       
   179 }
       
   180 
       
   181 extern EXPORT_C MP4Err MP4ParseOpenCAF(MP4Handle *apihandle,
       
   182                                                     ContentAccess::CData *inputfile)
       
   183 {
       
   184   MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
       
   185   *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
       
   186   if (*handle == NULL)
       
   187     return MP4_OUT_OF_MEMORY;
       
   188 
       
   189   (*handle)->file32Duplicate = NULL;
       
   190   (*handle)->cfile = inputfile;
       
   191   (*handle)->file = (*handle)->cfile;
       
   192   (*handle)->FileHandleFromOutside = ETrue;
       
   193   (*handle)->sourceType = MP4_SOURCE_CAF;
       
   194   
       
   195   if (inputfile == NULL)
       
   196       {
       
   197       closeFile(*handle);
       
   198       mp4free(*handle);
       
   199       *handle = NULL;
       
   200       return MP4_FILE_ERROR;
       
   201       }
       
   202 
       
   203   (*handle)->mem = listCreate();
       
   204   if ((*handle)->mem == NULL)
       
   205   {
       
   206     closeFile(*handle);
       
   207     mp4free(*handle);
       
   208     *handle = NULL;
       
   209     return MP4_OUT_OF_MEMORY;
       
   210   }
       
   211 
       
   212   if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
       
   213   {
       
   214     listDestroyList((*handle)->mem);
       
   215     closeFile(*handle);
       
   216     mp4free(*handle);
       
   217     *handle = NULL;
       
   218     return MP4_OUT_OF_MEMORY;
       
   219   }
       
   220 
       
   221   if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
       
   222   {
       
   223     mp4free((*handle)->buf);
       
   224     listDestroyList((*handle)->mem);
       
   225     closeFile(*handle);
       
   226     mp4free(*handle);
       
   227     *handle = NULL;
       
   228     return MP4_OUT_OF_MEMORY;
       
   229   }
       
   230 
       
   231 	// register for stblib use 
       
   232 	if (openStdlib() !=  MP4_OK)
       
   233 		{
       
   234 		// clean up
       
   235 		mp4free((*handle)->diskReadBuf);
       
   236 		mp4free((*handle)->buf);
       
   237 		listDestroyList((*handle)->mem);
       
   238 		closeFile(*handle);
       
   239 		mp4free(*handle);
       
   240 		*handle = NULL;
       
   241 
       
   242 		return MP4_ERROR;
       
   243 		} 
       
   244   
       
   245   return MP4_OK;
       
   246 }
       
   247 
       
   248 extern EXPORT_C MP4Err MP4ParseClose(MP4Handle apihandle)
       
   249 {
       
   250   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   251 
       
   252   if (!handle)
       
   253     return MP4_ERROR;
       
   254 
       
   255   if (handle->file)
       
   256     closeFile(handle);
       
   257 
       
   258   closeStdlib(); /* Free memory allocated by stdlib wrapper functions */
       
   259 
       
   260   listDestroyList(handle->mem);
       
   261 
       
   262   if (handle->diskReadBuf)
       
   263     mp4free(handle->diskReadBuf);
       
   264 
       
   265   if (handle->buf)
       
   266     mp4free(handle->buf);
       
   267   
       
   268   if (freeMOOV(handle->moov) < 0)
       
   269    	return MP4_ERROR;
       
   270 
       
   271   if (freeFTYP(handle->ftyp) < 0)
       
   272    	return MP4_ERROR;
       
   273 
       
   274   if (handle->file32Duplicate)
       
   275       ((RFile64*)handle->file32Duplicate)->Close();
       
   276   
       
   277   if (handle)
       
   278     mp4free(handle);
       
   279 
       
   280   return MP4_OK;
       
   281 }
       
   282 
       
   283 extern EXPORT_C MP4Err MP4ParseRequestVideoDescription(MP4Handle apihandle,
       
   284                                                                     mp4_u32 *videolength,
       
   285                                                                     mp4_double *framerate,
       
   286                                                                     mp4_u32 *videotype,
       
   287                                                                     mp4_u32 *videowidth,
       
   288                                                                     mp4_u32 *videoheight,
       
   289                                                                     mp4_u32 *timescale)
       
   290 {
       
   291   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   292   if (!handle)
       
   293 	  {
       
   294 	  return MP4_ERROR;
       
   295 	  }
       
   296 
       
   297   if (!handle->metaDataComplete)
       
   298   {
       
   299     switch (metaDataAvailable(handle))
       
   300     {
       
   301     case 0:
       
   302       return MP4_NOT_AVAILABLE;
       
   303 
       
   304     case 1:
       
   305       handle->cafError = KErrNone;
       
   306       if (readMetaData(handle) < 0)
       
   307       {
       
   308       	// Reading of meta data failed, so free up any allocated memory
       
   309   		freeFTYP(handle->ftyp);
       
   310   		handle->ftyp = NULL;
       
   311 		freeMOOV(handle->moov);
       
   312 		handle->moov = NULL;
       
   313       
       
   314       	if ( handle->cafError != KErrNone )
       
   315       	{
       
   316       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
   317       	  return handle->cafError;
       
   318       	}
       
   319       	else
       
   320       	{
       
   321 	      return MP4_INVALID_INPUT_STREAM;
       
   322       	}
       
   323       }
       
   324       handle->metaDataComplete = MP4TRUE;
       
   325       break;
       
   326 
       
   327     case -2:
       
   328       // Reading of FTYP meta data failed, so free up any allocated memory
       
   329       freeFTYP(handle->ftyp);
       
   330       handle->ftyp = NULL;
       
   331       return MP4_ERROR;      
       
   332       
       
   333     case -1:
       
   334     default:
       
   335       return MP4_ERROR;
       
   336     }
       
   337   }
       
   338 
       
   339   if (!handle->moov)
       
   340     return MP4_ERROR;
       
   341   if (!handle->moov->trakVideo)
       
   342     return MP4_NO_VIDEO;
       
   343   
       
   344   mp4_i32 videoError = 0;
       
   345   videoError = determineVideoType(handle, videotype);
       
   346   if ( videoError == -2 )
       
   347   {
       
   348     return MP4_NO_VIDEO;
       
   349   }
       
   350   else if ( videoError < 0 )
       
   351   {
       
   352   	return MP4_ERROR;
       
   353   }
       
   354 
       
   355   if (determineVideoLength(handle, videolength) < 0)
       
   356     return MP4_ERROR;
       
   357 
       
   358   if (determineFrameRate(handle, framerate) < 0)
       
   359     return MP4_ERROR;
       
   360 
       
   361   if (determineVideoResolution(handle, videowidth, videoheight) < 0)
       
   362     return MP4_ERROR;
       
   363 
       
   364   if (determineVideoTimeScale(handle, timescale) < 0)
       
   365     return MP4_ERROR;
       
   366 
       
   367 
       
   368   return MP4_OK;
       
   369 }
       
   370 
       
   371 extern EXPORT_C MP4Err MP4ParseRequestAudioDescription(MP4Handle apihandle,
       
   372                                                                     mp4_u32 *audiolength,
       
   373                                                                     mp4_u32 *audiotype,
       
   374                                                                     mp4_u8 *framespersample,
       
   375                                                                     mp4_u32 *timescale,
       
   376                                                                     mp4_u32 *averagebitrate)
       
   377 {
       
   378   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   379   if (!handle)
       
   380 	  {
       
   381 	  return MP4_ERROR;
       
   382 	  }
       
   383 
       
   384   if (!handle->metaDataComplete)
       
   385   {
       
   386     switch (metaDataAvailable(handle))
       
   387     {
       
   388     case 0:
       
   389       return MP4_NOT_AVAILABLE;
       
   390 
       
   391     case 1:
       
   392       handle->cafError = KErrNone;
       
   393       if (readMetaData(handle) < 0)
       
   394       {
       
   395       	// Reading of meta data failed, so free up any allocated memory
       
   396   		freeFTYP(handle->ftyp);
       
   397   		handle->ftyp = NULL;
       
   398 		freeMOOV(handle->moov);
       
   399 		handle->moov = NULL;
       
   400       
       
   401       	if ( handle->cafError != KErrNone )
       
   402       	{
       
   403       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
   404       	  return handle->cafError;
       
   405       	}
       
   406       	else
       
   407       	{
       
   408 	      return MP4_INVALID_INPUT_STREAM;
       
   409       	}
       
   410       }
       
   411 
       
   412       handle->metaDataComplete = MP4TRUE;
       
   413       break;
       
   414 
       
   415     case -2:
       
   416       // Reading of FTYP meta data failed, so free up any allocated memory
       
   417       freeFTYP(handle->ftyp);
       
   418       handle->ftyp = NULL;
       
   419       return MP4_ERROR;      
       
   420 
       
   421     case -1:
       
   422     default:
       
   423       return MP4_ERROR;
       
   424     }
       
   425   }
       
   426 
       
   427   if (!handle->moov)
       
   428     return MP4_ERROR;
       
   429   if (!handle->moov->trakAudio)
       
   430     return MP4_NO_AUDIO;
       
   431 
       
   432   if (determineAudioLength(handle, audiolength) < 0)
       
   433     return MP4_ERROR;
       
   434   
       
   435   mp4_i32 audioError = 0;
       
   436   audioError = determineAudioType(handle, audiotype);
       
   437   if ( audioError == -2 )
       
   438   {
       
   439     return MP4_NO_AUDIO;
       
   440   }
       
   441   else if ( audioError < 0 )
       
   442   {
       
   443   	return MP4_ERROR;
       
   444   }
       
   445 
       
   446   if (determineAudioFramesPerSample(handle, framespersample) < 0)
       
   447     return MP4_ERROR;
       
   448 
       
   449   if (determineAudioTimeScale(handle, timescale) < 0)
       
   450     return MP4_ERROR;
       
   451 
       
   452   if (averagebitrate != NULL)
       
   453     if (determineAudioAverageBitRate(handle, averagebitrate) < 0)
       
   454       return MP4_ERROR;
       
   455 
       
   456 
       
   457   return MP4_OK;
       
   458 }
       
   459 
       
   460 extern EXPORT_C MP4Err MP4ParseRequestStreamDescription(MP4Handle apihandle,
       
   461                                                                      mp4_u32 *streamsize,
       
   462                                                                      mp4_u32 *streamaveragebitrate)
       
   463 {
       
   464   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   465 
       
   466   if (!handle->metaDataComplete)
       
   467   {
       
   468     switch (metaDataAvailable(handle))
       
   469     {
       
   470     case 0:
       
   471 
       
   472       return MP4_NOT_AVAILABLE;
       
   473 
       
   474     case 1:
       
   475       handle->cafError = KErrNone;
       
   476       if (readMetaData(handle) < 0)
       
   477       {
       
   478       	// Reading of meta data failed, so free up any allocated memory
       
   479   		freeFTYP(handle->ftyp);
       
   480   		handle->ftyp = NULL;
       
   481 		freeMOOV(handle->moov);
       
   482 		handle->moov = NULL;
       
   483       
       
   484       	if ( handle->cafError != KErrNone )
       
   485       	{
       
   486       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
   487       	  return handle->cafError;
       
   488       	}
       
   489       	else
       
   490       	{
       
   491 	      return MP4_INVALID_INPUT_STREAM;
       
   492       	}
       
   493       }
       
   494       handle->metaDataComplete = MP4TRUE;
       
   495       break;
       
   496 
       
   497     case -2:
       
   498       // Reading of FTYP meta data failed, so free up any allocated memory
       
   499       freeFTYP(handle->ftyp);
       
   500       handle->ftyp = NULL;
       
   501       return MP4_ERROR;      
       
   502       
       
   503     case -1:
       
   504     default:
       
   505       return MP4_ERROR;
       
   506     }
       
   507   }
       
   508 
       
   509   if (determineStreamSize(handle, streamsize) < 0)
       
   510     return MP4_ERROR;
       
   511 
       
   512   if (determineStreamAverageBitRate(handle, streamaveragebitrate, *streamsize) < 0)
       
   513     return MP4_ERROR;
       
   514 
       
   515 
       
   516   return MP4_OK;
       
   517 }
       
   518 
       
   519 extern EXPORT_C MP4Err MP4ParseWriteData(MP4Handle apihandle,
       
   520                                                       mp4_u8 *buffer,
       
   521                                                       mp4_u32 bytestowrite)
       
   522 {
       
   523   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   524 
       
   525   if (handle->file)
       
   526     return MP4_ERROR;
       
   527 
       
   528   if ((buffer == NULL) && (bytestowrite != 0))
       
   529       return MP4_ERROR;
       
   530 
       
   531   if (handle->LastWriteDataCalled == MP4TRUE)
       
   532       return MP4_ERROR;  // WriteData() call has been made before with bytestowrite=0, can not call again.
       
   533 
       
   534   if (bytestowrite != 0)
       
   535   {
       
   536       if (addData(handle, buffer, bytestowrite) == -1)
       
   537         return MP4_OUT_OF_MEMORY;
       
   538   }
       
   539   else  
       
   540       handle->LastWriteDataCalled = MP4TRUE;
       
   541 
       
   542 
       
   543   return MP4_OK;
       
   544 }
       
   545 
       
   546 extern EXPORT_C MP4Err MP4ParseGetBufferedBytes(MP4Handle apihandle,
       
   547                                                              mp4_u32 *bytes)
       
   548 {
       
   549   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   550 
       
   551   *bytes = getBufferedBytes(handle);
       
   552 
       
   553   if (handle->file)
       
   554     return MP4_FILE_MODE;
       
   555 
       
   556   return MP4_OK;
       
   557 }
       
   558 
       
   559 extern EXPORT_C MP4Err MP4ParseNextFrameType(MP4Handle apihandle,
       
   560                                                           mp4_u32 *type)
       
   561 	{
       
   562 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   563 
       
   564 	if (!handle->metaDataComplete)
       
   565 		{
       
   566 		switch (metaDataAvailable(handle))
       
   567 			{
       
   568 			case 0:
       
   569 				return MP4_NOT_AVAILABLE;
       
   570 
       
   571 			case 1:
       
   572 				handle->cafError = KErrNone;
       
   573 				if (readMetaData(handle) < 0)
       
   574 					{
       
   575 			      	// Reading of meta data failed, so free up any allocated memory
       
   576 			  		freeFTYP(handle->ftyp);
       
   577 			  		handle->ftyp = NULL;
       
   578 					freeMOOV(handle->moov);
       
   579 					handle->moov = NULL;
       
   580 					
       
   581 					if ( handle->cafError != KErrNone )
       
   582 						{
       
   583 						// if CAF/DRM caused the error return it instead of generic errorcode.
       
   584 						return handle->cafError;
       
   585 						}
       
   586 					else
       
   587 						{
       
   588 						return MP4_INVALID_INPUT_STREAM;
       
   589 						}
       
   590 					}
       
   591 				handle->metaDataComplete = MP4TRUE;
       
   592 				break;
       
   593 
       
   594 		    case -2:
       
   595 		      // Reading of FTYP meta data failed, so free up any allocated memory
       
   596 		      freeFTYP(handle->ftyp);
       
   597 		      handle->ftyp = NULL;
       
   598 		      return MP4_ERROR;      
       
   599 				
       
   600 			case -1:
       
   601 			default:
       
   602 				return MP4_ERROR;
       
   603 			}
       
   604 		}
       
   605 
       
   606 	/* No audio nor video */
       
   607 	if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo))
       
   608 		return MP4_ERROR;
       
   609   
       
   610 	mp4_u32 audiotype = 0;
       
   611 	mp4_i32 audioerror = 0; 
       
   612 	if (handle->moov->trakAudio)
       
   613 		{
       
   614 		audioerror = determineAudioType(handle, &audiotype);
       
   615 		}
       
   616   
       
   617 	mp4_u32 videotype = 0;
       
   618 	mp4_i32 videoerror = 0;
       
   619 	if (handle->moov->trakVideo)
       
   620 		{
       
   621 		videoerror = determineVideoType(handle, &videotype);
       
   622 		}
       
   623 
       
   624 	/* Audio track only */
       
   625 	if (handle->moov->trakAudio && !handle->moov->trakVideo)
       
   626 		{
       
   627 		if (audioerror == 0)
       
   628 			{
       
   629 			// if audio is of supported type, check if the last audio frame has been 
       
   630 			// retrieved
       
   631 			if (handle->audioLast)
       
   632 				{
       
   633 				return MP4_NO_FRAME;
       
   634 				}
       
   635 			else
       
   636 				{
       
   637 				*type = audiotype;
       
   638 				return MP4_OK;
       
   639 				}
       
   640 			}
       
   641 		else
       
   642 			{
       
   643 			return MP4_ERROR;
       
   644 			}
       
   645 		}
       
   646 
       
   647 	/* Video track only */
       
   648 	if (handle->moov->trakVideo && !handle->moov->trakAudio)
       
   649 		{
       
   650 		if (videoerror == 0)
       
   651 			{
       
   652 			// if video is of supported type, check if the last video frame has been 
       
   653 			// retrieved			
       
   654 			if (handle->videoLast)
       
   655 				{
       
   656 				return MP4_NO_FRAME;
       
   657 				}
       
   658 			else
       
   659 				{
       
   660 				*type = videotype;
       
   661 				return MP4_OK;
       
   662 				}
       
   663 			}
       
   664 		else
       
   665 			{
       
   666 			return MP4_ERROR;
       
   667 			}
       
   668 		}
       
   669 
       
   670 	/* All audio has been read, but there is video left */
       
   671 	if (handle->audioLast && !handle->videoLast)
       
   672 		{
       
   673 		if (videoerror == 0)
       
   674 			{
       
   675 			*type = videotype;
       
   676 			return MP4_OK;
       
   677 			}
       
   678 		else
       
   679 			{
       
   680 			return MP4_ERROR;
       
   681 			}
       
   682 		}
       
   683 
       
   684 	/* All video has been read, but there is audio left */
       
   685 	if (handle->videoLast && !handle->audioLast)
       
   686 		{
       
   687 		if (audioerror == 0)
       
   688 			{
       
   689 			*type = audiotype;
       
   690 			return MP4_OK;
       
   691 			}
       
   692 		else
       
   693 			{
       
   694 			return MP4_ERROR;
       
   695 			}
       
   696 		}
       
   697 
       
   698 	/* All data has been read */
       
   699 	if (handle->audioLast && handle->videoLast)
       
   700 		{
       
   701 		return MP4_NO_FRAME;
       
   702 		}
       
   703 
       
   704 	if (handle->audioSampleOffset < handle->videoFrameOffset)
       
   705 		{
       
   706 		/* Next frame is audio */
       
   707 		if (audioerror == 0)
       
   708 			{
       
   709 			*type = audiotype;
       
   710 			return MP4_OK;
       
   711 			}
       
   712 		else if ( (audioerror == -2) && (videoerror == 0) )
       
   713 			{
       
   714 			*type = videotype;
       
   715 			return MP4_OK;		
       
   716 			}
       
   717 		else
       
   718 			{
       
   719 			return MP4_ERROR;
       
   720 			}
       
   721 		}
       
   722 	else
       
   723 		{
       
   724 		/* Next frame is video */
       
   725 		if (videoerror == 0)
       
   726 			{
       
   727 			*type = videotype;
       
   728 			return MP4_OK;
       
   729 			}
       
   730 		else if ( (videoerror == -2) && (audioerror == 0) )
       
   731 			{
       
   732 			*type = audiotype;
       
   733 			return MP4_OK;		
       
   734 			}
       
   735 		else
       
   736 			{
       
   737 			return MP4_ERROR;
       
   738 			}
       
   739 		}
       
   740 	}
       
   741 
       
   742 extern EXPORT_C MP4Err MP4ParseNextFrameSize(MP4Handle apihandle,
       
   743                                                           mp4_u32 type,
       
   744                                                           mp4_u32 *framesize)
       
   745 {
       
   746   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   747 
       
   748   if (!handle->metaDataComplete)
       
   749   {
       
   750     switch (metaDataAvailable(handle))
       
   751     {
       
   752     case 0:
       
   753 
       
   754       return MP4_NOT_AVAILABLE;
       
   755 
       
   756     case 1:
       
   757       handle->cafError = KErrNone;
       
   758       if (readMetaData(handle) < 0)
       
   759       {
       
   760       	// Reading of meta data failed, so free up any allocated memory
       
   761   		freeFTYP(handle->ftyp);
       
   762   		handle->ftyp = NULL;
       
   763 		freeMOOV(handle->moov);
       
   764 		handle->moov = NULL;
       
   765       
       
   766       	if ( handle->cafError != KErrNone )
       
   767       	{
       
   768       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
   769       	  return handle->cafError;
       
   770       	}
       
   771       	else
       
   772       	{
       
   773 	      return MP4_INVALID_INPUT_STREAM;
       
   774       	}
       
   775       }
       
   776 
       
   777       handle->metaDataComplete = MP4TRUE;
       
   778       break;
       
   779 
       
   780     case -2:
       
   781       // Reading of FTYP meta data failed, so free up any allocated memory
       
   782       freeFTYP(handle->ftyp);
       
   783       handle->ftyp = NULL;
       
   784       return MP4_ERROR;            
       
   785       
       
   786     case -1:
       
   787     default:
       
   788       return MP4_ERROR;
       
   789     }
       
   790   }
       
   791 
       
   792   switch (type & handle->type)
       
   793   {
       
   794   case MP4_TYPE_MPEG4_VIDEO:
       
   795   case MP4_TYPE_H263_PROFILE_0:
       
   796   case MP4_TYPE_H263_PROFILE_3:
       
   797   case MP4_TYPE_AVC_PROFILE_BASELINE:
       
   798   case MP4_TYPE_AVC_PROFILE_MAIN:
       
   799   case MP4_TYPE_AVC_PROFILE_EXTENDED:
       
   800   case MP4_TYPE_AVC_PROFILE_HIGH:
       
   801   
       
   802     /* There is a next video frame */
       
   803 
       
   804     if (!handle->videoLast)
       
   805       *framesize = handle->videoFrameSize;
       
   806     else
       
   807     {
       
   808       *framesize = 0;
       
   809 
       
   810       return MP4_NO_REQUESTED_FRAME;
       
   811     }
       
   812 
       
   813     break;
       
   814 
       
   815   case MP4_TYPE_MPEG4_AUDIO:
       
   816   case MP4_TYPE_AMR_NB:
       
   817   case MP4_TYPE_AMR_WB:
       
   818   case MP4_TYPE_QCELP_13K:
       
   819 
       
   820     /* There is a next audio frame */
       
   821 
       
   822     if (!handle->audioLast)
       
   823       *framesize = handle->audioSampleSize;
       
   824     else
       
   825     {
       
   826       *framesize = 0;
       
   827 
       
   828       return MP4_NO_REQUESTED_FRAME;
       
   829     }
       
   830 
       
   831     break;
       
   832 
       
   833   case MP4_TYPE_NONE:
       
   834   default:
       
   835 
       
   836     if (type == MP4_TYPE_MPEG4_VIDEO ||
       
   837         type == MP4_TYPE_H263_PROFILE_0 ||
       
   838         type == MP4_TYPE_H263_PROFILE_3 ||
       
   839         type == MP4_TYPE_MPEG4_AUDIO ||
       
   840         type == MP4_TYPE_AMR_NB ||
       
   841         type == MP4_TYPE_AMR_WB ||
       
   842 		isAvcVideo(type) ||
       
   843         type == MP4_TYPE_QCELP_13K
       
   844         )
       
   845       return MP4_NO_REQUESTED_FRAME;
       
   846 
       
   847     return MP4_INVALID_TYPE;
       
   848   }
       
   849 
       
   850   return MP4_OK;
       
   851 }
       
   852 
       
   853 extern EXPORT_C MP4Err MP4ParseReadVideoFrame(MP4Handle apihandle,
       
   854                                                            mp4_u8 *buffer,
       
   855                                                            mp4_u32 buffersize,
       
   856                                                            mp4_u32 *framesize,
       
   857                                                            mp4_u32 *timestamp,
       
   858                                                            mp4_bool *keyframe,
       
   859                                                            mp4_u32 *timestamp2)
       
   860 {
       
   861   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   862 
       
   863   if (!handle->metaDataComplete)
       
   864   {
       
   865     switch (metaDataAvailable(handle))
       
   866     {
       
   867     case 0:
       
   868 
       
   869       return MP4_NOT_AVAILABLE;
       
   870 
       
   871     case 1:
       
   872       handle->cafError = KErrNone;
       
   873       if (readMetaData(handle) < 0)
       
   874       {
       
   875       	// Reading of meta data failed, so free up any allocated memory
       
   876   		freeFTYP(handle->ftyp);
       
   877   		handle->ftyp = NULL;
       
   878 		freeMOOV(handle->moov);
       
   879 		handle->moov = NULL;
       
   880       
       
   881       	if ( handle->cafError != KErrNone )
       
   882       	{
       
   883       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
   884       	  return handle->cafError;
       
   885       	}
       
   886       	else
       
   887       	{
       
   888 	      return MP4_INVALID_INPUT_STREAM;
       
   889       	}
       
   890       }
       
   891       handle->metaDataComplete = MP4TRUE;
       
   892       break;
       
   893 
       
   894     case -2:
       
   895       // Reading of FTYP meta data failed, so free up any allocated memory
       
   896       freeFTYP(handle->ftyp);
       
   897       handle->ftyp = NULL;
       
   898       return MP4_ERROR;      
       
   899       
       
   900     case -1:
       
   901     default:
       
   902       return MP4_ERROR;
       
   903     }
       
   904   }
       
   905 
       
   906   /* Is video available? */
       
   907 
       
   908   if (!((handle->type & MP4_TYPE_MPEG4_VIDEO) ||
       
   909         (handle->type & MP4_TYPE_H263_PROFILE_0) ||
       
   910         (handle->type & MP4_TYPE_H263_PROFILE_3) ||
       
   911 		containsAvcVideo( handle->type ) ))
       
   912     return MP4_ERROR;
       
   913 
       
   914   /* Are there samples left? */
       
   915 
       
   916   if (handle->videoLast)
       
   917     return MP4_NO_FRAME;
       
   918 
       
   919   if (!handle->moov)
       
   920     return MP4_ERROR;
       
   921   if (!handle->moov->trakVideo)
       
   922     return MP4_ERROR;
       
   923 
       
   924   switch (fetchVideoFrame(handle, handle->moov->trakVideo, buffer, buffersize, framesize, timestamp, keyframe, timestamp2))
       
   925   {
       
   926   case -1:
       
   927     return MP4_ERROR;
       
   928   case -2:
       
   929     return MP4_BUFFER_TOO_SMALL;
       
   930   case -3:
       
   931     return MP4_NOT_AVAILABLE;
       
   932   case -4:
       
   933     return MP4_INVALID_INPUT_STREAM;
       
   934   default:
       
   935     break;
       
   936   }
       
   937 
       
   938   switch (advanceVideoFrame(handle, handle->moov->trakVideo))
       
   939   {
       
   940   case -1:
       
   941     return MP4_ERROR;
       
   942   case -2:
       
   943     handle->videoLast = MP4TRUE;
       
   944     break;
       
   945   default:
       
   946     break;
       
   947   }
       
   948 
       
   949   return MP4_OK;
       
   950 }
       
   951 
       
   952 extern EXPORT_C MP4Err MP4ParseReadVideoDecoderSpecificInfo(MP4Handle apihandle,
       
   953                                                                          mp4_u8 *buffer,
       
   954                                                                          mp4_u32 buffersize,
       
   955                                                                          mp4_u32 *decspecinfosize)
       
   956 	{
       
   957 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
   958 	if (!handle->metaDataComplete)
       
   959 		{
       
   960 		switch (metaDataAvailable(handle))
       
   961 			{
       
   962 			case 0:
       
   963 				return MP4_NOT_AVAILABLE;
       
   964 
       
   965 			case 1:
       
   966 				handle->cafError = KErrNone;
       
   967 				if (readMetaData(handle) < 0)
       
   968 					{
       
   969 			      	// Reading of meta data failed, so free up any allocated memory
       
   970 			  		freeFTYP(handle->ftyp);
       
   971 			  		handle->ftyp = NULL;
       
   972 					freeMOOV(handle->moov);
       
   973 					handle->moov = NULL;
       
   974 					
       
   975 					if ( handle->cafError != KErrNone )
       
   976 						{
       
   977 						// if CAF/DRM caused the error return it instead of generic errorcode.
       
   978 						return handle->cafError;
       
   979 						}
       
   980 					else
       
   981 						{
       
   982 						return MP4_INVALID_INPUT_STREAM;
       
   983 						}
       
   984 					}
       
   985 				handle->metaDataComplete = MP4TRUE;
       
   986 				break;
       
   987 
       
   988 		    case -2:
       
   989 		      // Reading of FTYP meta data failed, so free up any allocated memory
       
   990 		      freeFTYP(handle->ftyp);
       
   991 		      handle->ftyp = NULL;
       
   992 		      return MP4_ERROR;      
       
   993 
       
   994 			case -1:
       
   995 			default:
       
   996 				return MP4_ERROR;
       
   997 			}
       
   998 		}
       
   999 
       
  1000 	/* Is video type MPEG or AVC? */
       
  1001 	if (!(handle->type & MP4_TYPE_MPEG4_VIDEO) && 
       
  1002 	   !(containsAvcVideo( handle->type )) )
       
  1003 		{
       
  1004 		return MP4_ERROR;
       
  1005 		}
       
  1006 
       
  1007 	if (!handle->moov)
       
  1008 		{
       
  1009 		return MP4_ERROR;
       
  1010 		}
       
  1011 	if (!handle->moov->trakVideo)
       
  1012 		{
       
  1013 		return MP4_ERROR;
       
  1014 		}
       
  1015 	if (!handle->moov->trakVideo->mdia)
       
  1016 		{
       
  1017 		return MP4_ERROR;
       
  1018 		}
       
  1019 	if (!handle->moov->trakVideo->mdia->minf)
       
  1020 		{
       
  1021 		return MP4_ERROR;
       
  1022 		}
       
  1023 	if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  1024 		{
       
  1025 		return MP4_ERROR;
       
  1026 		}
       
  1027 	if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
       
  1028 		{
       
  1029 		return MP4_ERROR;
       
  1030 		}
       
  1031 	if (handle->videoSampleEntryIndex > handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount)
       
  1032 		{
       
  1033 		return MP4_ERROR;
       
  1034 		}			
       
  1035 
       
  1036 	TInt index = handle->videoSampleEntryIndex - 1;		  
       
  1037 	if (handle->videoSampleEntryIndex == 0)			  
       
  1038 		{
       
  1039 		// even though the video sample contains no actual data, if the video sample exist
       
  1040 		// and contains decoder specific info, return it anyway
       
  1041 		index = 0;
       
  1042 		}
       
  1043 	
       
  1044 	if (handle->type & MP4_TYPE_MPEG4_VIDEO)
       
  1045 		{
       
  1046 		/* Copy DecoderSpecificInfo into buffer */
       
  1047 		if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index])
       
  1048 			{
       
  1049 			return MP4_ERROR;
       
  1050 			}
       
  1051 		if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd)
       
  1052 			{
       
  1053 			return MP4_ERROR;
       
  1054 			}
       
  1055 
       
  1056 		*decspecinfosize = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize;
       
  1057 		if (buffersize < handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize)
       
  1058 			{
       
  1059 			return MP4_BUFFER_TOO_SMALL;
       
  1060 			}
       
  1061 
       
  1062 		mp4memcpy(buffer, 
       
  1063 				  handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfo,
       
  1064 				  handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize);
       
  1065 		}
       
  1066   	else if ( containsAvcVideo( handle->type ) )
       
  1067   		{
       
  1068   		/* Copy the AVCDecoderConfigurationRecord into buffer */
       
  1069   		if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index])
       
  1070   			{
       
  1071   			return MP4_ERROR;
       
  1072   			}
       
  1073   		if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc)
       
  1074   			{
       
  1075   			return MP4_ERROR;
       
  1076   			}
       
  1077 
       
  1078   		*decspecinfosize = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize;
       
  1079   		if (buffersize < handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize)
       
  1080   			{
       
  1081   			return MP4_BUFFER_TOO_SMALL;
       
  1082   			}
       
  1083 
       
  1084   		mp4memcpy(buffer,
       
  1085   				  handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfig,
       
  1086 				  handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize);
       
  1087   		}
       
  1088 
       
  1089 	return MP4_OK;
       
  1090 	}
       
  1091 
       
  1092 extern EXPORT_C MP4Err MP4ParseReadAudioFrames(MP4Handle apihandle,
       
  1093                                                             mp4_u8 *buffer,
       
  1094                                                             mp4_u32 buffersize,
       
  1095                                                             mp4_u32 *audiosize,
       
  1096                                                             mp4_u32 *timestamp,
       
  1097                                                             mp4_u32 *returnedframes,
       
  1098                                                             mp4_u32 *timestamp2)
       
  1099 {
       
  1100   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1101 
       
  1102   if (!handle->metaDataComplete)
       
  1103   {
       
  1104     switch (metaDataAvailable(handle))
       
  1105     {
       
  1106     case 0:
       
  1107       return MP4_NOT_AVAILABLE;
       
  1108 
       
  1109     case 1:
       
  1110       handle->cafError = KErrNone;
       
  1111       if (readMetaData(handle) < 0)
       
  1112       {
       
  1113       	// Reading of meta data failed, so free up any allocated memory
       
  1114   		freeFTYP(handle->ftyp);
       
  1115   		handle->ftyp = NULL;
       
  1116 		freeMOOV(handle->moov);
       
  1117 		handle->moov = NULL;
       
  1118       
       
  1119       	if ( handle->cafError != KErrNone )
       
  1120       	{
       
  1121       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
  1122       	  return handle->cafError;
       
  1123       	}
       
  1124       	else
       
  1125       	{
       
  1126 	      return MP4_INVALID_INPUT_STREAM;
       
  1127       	}
       
  1128       }
       
  1129       handle->metaDataComplete = MP4TRUE;
       
  1130       break;
       
  1131 
       
  1132     case -2:
       
  1133       // Reading of FTYP meta data failed, so free up any allocated memory
       
  1134       freeFTYP(handle->ftyp);
       
  1135       handle->ftyp = NULL;
       
  1136       return MP4_ERROR;      
       
  1137       
       
  1138     case -1:
       
  1139     default:
       
  1140       return MP4_ERROR;
       
  1141     }
       
  1142   }
       
  1143 
       
  1144   /* Is audio available? */
       
  1145 
       
  1146   if (!((handle->type & MP4_TYPE_MPEG4_AUDIO) ||
       
  1147         (handle->type & MP4_TYPE_AMR_NB) ||
       
  1148         (handle->type & MP4_TYPE_AMR_WB) ||
       
  1149         (handle->type & MP4_TYPE_QCELP_13K)))
       
  1150     return MP4_ERROR;
       
  1151 
       
  1152   /* Are there samples left? */
       
  1153 
       
  1154   if (handle->audioLast)
       
  1155     return MP4_NO_FRAME;
       
  1156 
       
  1157   if (!handle->moov)
       
  1158     return MP4_ERROR;
       
  1159   if (!handle->moov->trakAudio)
       
  1160     return MP4_ERROR;
       
  1161 
       
  1162   switch (fetchAudioSample(handle, handle->moov->trakAudio, buffer, buffersize, audiosize, timestamp, returnedframes, timestamp2))
       
  1163   {
       
  1164   case -1:
       
  1165     return MP4_ERROR;
       
  1166   case -2:
       
  1167     return MP4_BUFFER_TOO_SMALL;
       
  1168   case -3:
       
  1169     return MP4_NOT_AVAILABLE;
       
  1170   case -4:
       
  1171     return MP4_INVALID_INPUT_STREAM;
       
  1172   default:
       
  1173     break;
       
  1174   }
       
  1175 
       
  1176   switch (advanceAudioSample(handle, handle->moov->trakAudio))
       
  1177   {
       
  1178   case -1:
       
  1179     return MP4_ERROR;
       
  1180   case -2:
       
  1181     handle->audioLast = MP4TRUE;
       
  1182     break;
       
  1183   default:
       
  1184     break;
       
  1185   }
       
  1186 
       
  1187   return MP4_OK;
       
  1188 }
       
  1189 
       
  1190 extern EXPORT_C MP4Err MP4ParseReadAudioDecoderSpecificInfo(MP4Handle apihandle,
       
  1191                                                                          mp4_u8 *buffer,
       
  1192                                                                          mp4_u32 buffersize,
       
  1193                                                                          mp4_u32 *decspecinfosize)
       
  1194 	{
       
  1195 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1196 
       
  1197 	if (!handle->metaDataComplete)
       
  1198 		{
       
  1199 		switch (metaDataAvailable(handle))
       
  1200 			{
       
  1201 			case 0:
       
  1202 				return MP4_NOT_AVAILABLE;
       
  1203 
       
  1204 			case 1:
       
  1205 				handle->cafError = KErrNone;
       
  1206 				if (readMetaData(handle) < 0)
       
  1207 					{
       
  1208 			      	// Reading of meta data failed, so free up any allocated memory
       
  1209 			  		freeFTYP(handle->ftyp);
       
  1210 			  		handle->ftyp = NULL;
       
  1211 					freeMOOV(handle->moov);
       
  1212 					handle->moov = NULL;
       
  1213 					
       
  1214 					if ( handle->cafError != KErrNone )
       
  1215 						{
       
  1216 						// if CAF/DRM caused the error return it instead of generic errorcode.
       
  1217 						return handle->cafError;
       
  1218 						}
       
  1219 					else
       
  1220 						{
       
  1221 						return MP4_INVALID_INPUT_STREAM;
       
  1222 						}
       
  1223 					}
       
  1224 				handle->metaDataComplete = MP4TRUE;
       
  1225 				break;
       
  1226 
       
  1227 		    case -2:
       
  1228 		      // Reading of FTYP meta data failed, so free up any allocated memory
       
  1229 		      freeFTYP(handle->ftyp);
       
  1230 		      handle->ftyp = NULL;
       
  1231 		      return MP4_ERROR;      
       
  1232 				
       
  1233 			case -1:
       
  1234 			default:
       
  1235 				return MP4_ERROR;
       
  1236 			}
       
  1237 		}
       
  1238 
       
  1239     if (!handle->moov)
       
  1240     	{
       
  1241     	return MP4_ERROR;
       
  1242     	}
       
  1243     if (!handle->moov->trakAudio)
       
  1244     	{
       
  1245     	return MP4_ERROR;
       
  1246     	}
       
  1247     if (!handle->moov->trakAudio->mdia)
       
  1248     	{
       
  1249     	return MP4_ERROR;
       
  1250     	}
       
  1251     if (!handle->moov->trakAudio->mdia->minf)
       
  1252     	{
       
  1253     	return MP4_ERROR;
       
  1254     	}
       
  1255     if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  1256     	{
       
  1257     	return MP4_ERROR;
       
  1258     	}
       
  1259     if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
       
  1260     	{
       
  1261     	return MP4_ERROR;
       
  1262     	}
       
  1263 	
       
  1264     
       
  1265 	TInt index = handle->audioSampleEntryIndex - 1;		  
       
  1266 	if (handle->audioSampleEntryIndex == 0)			  
       
  1267 		{
       
  1268 		// even though the audio sample contains no actual data, if the audio sample exist
       
  1269 		// and contains decoder specific info, return it anyway
       
  1270 		index = 0;
       
  1271 		}
       
  1272     
       
  1273 	/* Audio type */
       
  1274 	if ((handle->type & MP4_TYPE_MPEG4_AUDIO) || 
       
  1275 		((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)))
       
  1276 		{
       
  1277 		/* Copy DecoderSpecificInfo into buffer */
       
  1278 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index])
       
  1279 			{
       
  1280 			return MP4_ERROR;
       
  1281 			}
       
  1282 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd)
       
  1283 			{
       
  1284 			return MP4_ERROR;
       
  1285 			}
       
  1286 
       
  1287 		*decspecinfosize = handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize;
       
  1288 		if (buffersize < handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize)
       
  1289 			{
       
  1290 			return MP4_BUFFER_TOO_SMALL;
       
  1291 			}
       
  1292 
       
  1293 		mp4memcpy(buffer,
       
  1294 				  handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfo,
       
  1295 				  handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize);
       
  1296 		}
       
  1297 	else if ((handle->type & MP4_TYPE_AMR_NB) || 
       
  1298 			 (handle->type & MP4_TYPE_AMR_WB) || 
       
  1299 			 ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)))
       
  1300 		{
       
  1301 		/* Copy DecoderSpecificInfo into buffer */
       
  1302 		if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index] == NULL &&
       
  1303 			handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index] == NULL &&
       
  1304             handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index] == NULL)
       
  1305 			{
       
  1306 			return MP4_ERROR;
       
  1307 			}
       
  1308 
       
  1309 		if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index])
       
  1310 			{
       
  1311 			if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr)
       
  1312 				{
       
  1313 				return MP4_ERROR;
       
  1314 				}
       
  1315 
       
  1316 			*decspecinfosize = 9;
       
  1317 			if (buffersize < *decspecinfosize)
       
  1318 				{
       
  1319 				return MP4_BUFFER_TOO_SMALL;
       
  1320 				}
       
  1321 
       
  1322 			mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->vendor), 4);
       
  1323 			mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->decoderVersion), 1);
       
  1324 			mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->modeSet), 2);
       
  1325 			mp4memcpy(buffer+7, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->modeChangePeriod), 1);
       
  1326 			mp4memcpy(buffer+8, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->framesPerSample), 1);
       
  1327 			}
       
  1328 
       
  1329 		if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index])
       
  1330 			{
       
  1331 			if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr)
       
  1332 				{
       
  1333 				return MP4_ERROR;
       
  1334 				}
       
  1335 
       
  1336 			*decspecinfosize = 9;
       
  1337 			if (buffersize < *decspecinfosize)
       
  1338 				{
       
  1339 				return MP4_BUFFER_TOO_SMALL;
       
  1340 				}
       
  1341 
       
  1342 			mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->vendor), 4);
       
  1343 			mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->decoderVersion), 1);
       
  1344 			mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->modeSet), 2);
       
  1345 			mp4memcpy(buffer+7, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->modeChangePeriod), 1);
       
  1346 			mp4memcpy(buffer+8, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->framesPerSample), 1);
       
  1347 			}
       
  1348 
       
  1349 		if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index])
       
  1350 			{
       
  1351 			if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp)
       
  1352 				{
       
  1353 				return MP4_ERROR;
       
  1354 				}
       
  1355 
       
  1356 			*decspecinfosize = 6;
       
  1357 			if (buffersize < *decspecinfosize)
       
  1358 				{
       
  1359 				return MP4_BUFFER_TOO_SMALL;
       
  1360 				}
       
  1361 
       
  1362 			mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->vendor), 4);
       
  1363 			mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->decoderVersion), 1);
       
  1364 			mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->framesPerSample), 1);
       
  1365 			}
       
  1366 		}
       
  1367 	else
       
  1368 		{
       
  1369 		return MP4_ERROR;
       
  1370 		}
       
  1371 	
       
  1372 	return MP4_OK;
       
  1373 	}
       
  1374 
       
  1375 extern EXPORT_C MP4Err MP4ParseGetNextVideoTimestamp(MP4Handle apihandle,
       
  1376                                                                   mp4_u32 *timestamp,
       
  1377                                                                   mp4_u32 *timestamp2)
       
  1378 {
       
  1379   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1380 
       
  1381   if (!handle->metaDataComplete)
       
  1382   {
       
  1383     switch (metaDataAvailable(handle))
       
  1384     {
       
  1385     case 0:
       
  1386 
       
  1387       return MP4_NOT_AVAILABLE;
       
  1388 
       
  1389     case 1:
       
  1390       handle->cafError = KErrNone;
       
  1391       if (readMetaData(handle) < 0)
       
  1392       {
       
  1393       	// Reading of meta data failed, so free up any allocated memory
       
  1394   		freeFTYP(handle->ftyp);
       
  1395   		handle->ftyp = NULL;
       
  1396 		freeMOOV(handle->moov);
       
  1397 		handle->moov = NULL;
       
  1398       
       
  1399       	if ( handle->cafError != KErrNone )
       
  1400       	{
       
  1401       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
  1402       	  return handle->cafError;
       
  1403       	}
       
  1404       	else
       
  1405       	{
       
  1406 	      return MP4_INVALID_INPUT_STREAM;
       
  1407       	}
       
  1408       }
       
  1409       handle->metaDataComplete = MP4TRUE;
       
  1410       break;
       
  1411 
       
  1412     case -2:
       
  1413       // Reading of FTYP meta data failed, so free up any allocated memory
       
  1414       freeFTYP(handle->ftyp);
       
  1415       handle->ftyp = NULL;
       
  1416       return MP4_ERROR;      
       
  1417       
       
  1418     case -1:
       
  1419     default:
       
  1420       return MP4_ERROR;
       
  1421     }
       
  1422   }
       
  1423 
       
  1424   if (!handle->moov)
       
  1425     return MP4_ERROR;
       
  1426 
       
  1427   if (!handle->moov->trakVideo)
       
  1428     return MP4_ERROR;
       
  1429 
       
  1430   if (!handle->moov->trakVideo->mdia)
       
  1431     return MP4_ERROR;
       
  1432 
       
  1433   if (handle->videoLast)
       
  1434     return MP4_END_OF_VIDEO;
       
  1435 
       
  1436   if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, timestamp, timestamp2) < 0)
       
  1437     return MP4_ERROR;
       
  1438 
       
  1439   switch (advanceVideoFrame(handle, handle->moov->trakVideo))
       
  1440   {
       
  1441   case -1:
       
  1442     return MP4_ERROR;
       
  1443   case -2:
       
  1444     handle->videoLast = MP4TRUE;
       
  1445     break;
       
  1446   default:
       
  1447     break;
       
  1448   }
       
  1449 
       
  1450   return MP4_OK;
       
  1451 }
       
  1452 
       
  1453 extern EXPORT_C MP4Err MP4ParseIsStreamable(MP4Handle apihandle)
       
  1454 {
       
  1455   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1456 
       
  1457   if (!handle->metaDataComplete)
       
  1458   {
       
  1459     switch (metaDataAvailable(handle))
       
  1460     {
       
  1461     case 0:
       
  1462 
       
  1463       return MP4_NOT_AVAILABLE;
       
  1464 
       
  1465     case 1:
       
  1466       handle->cafError = KErrNone;
       
  1467       if (readMetaData(handle) < 0)
       
  1468       {
       
  1469       	// Reading of meta data failed, so free up any allocated memory
       
  1470   		freeFTYP(handle->ftyp);
       
  1471   		handle->ftyp = NULL;
       
  1472 		freeMOOV(handle->moov);
       
  1473 		handle->moov = NULL;
       
  1474       
       
  1475       	if ( handle->cafError != KErrNone )
       
  1476       	{
       
  1477       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
  1478       	  return handle->cafError;
       
  1479       	}
       
  1480       	else
       
  1481       	{
       
  1482 	      return MP4_INVALID_INPUT_STREAM;
       
  1483       	}
       
  1484       }
       
  1485       handle->metaDataComplete = MP4TRUE;
       
  1486       break;
       
  1487 
       
  1488     case -2:
       
  1489       // Reading of FTYP meta data failed, so free up any allocated memory
       
  1490       freeFTYP(handle->ftyp);
       
  1491       handle->ftyp = NULL;
       
  1492       return MP4_ERROR;      
       
  1493 
       
  1494     case -1:
       
  1495     default:
       
  1496       return MP4_ERROR;
       
  1497     }
       
  1498   }
       
  1499 
       
  1500   /* There is no audio nor video */
       
  1501 
       
  1502   if (!handle->audioSampleNum && !handle->videoSampleNum)
       
  1503     return MP4_ERROR;
       
  1504 
       
  1505   /* There is audio, but no video */
       
  1506 
       
  1507   if (handle->audioSampleNum && !handle->videoSampleNum)
       
  1508   {
       
  1509     if (!handle->moov)
       
  1510       return MP4_ERROR;
       
  1511 
       
  1512     if (!handle->moov->trakAudio)
       
  1513       return MP4_ERROR;
       
  1514 
       
  1515     if (!handle->moov->trakAudio->mdia)
       
  1516       return MP4_ERROR;
       
  1517 
       
  1518     if (!handle->moov->trakAudio->mdia->minf)
       
  1519       return MP4_ERROR;
       
  1520 
       
  1521     if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  1522       return MP4_ERROR;
       
  1523 
       
  1524     if (!handle->moov->trakAudio->mdia->minf->stbl->stco)
       
  1525       return MP4_ERROR;
       
  1526 
       
  1527     if (handle->moov->trakAudio->mdia->minf->stbl->stco->entryCount < 2)
       
  1528       return MP4_OK;
       
  1529     
       
  1530     if (getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 0) <
       
  1531         getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 1))
       
  1532       return MP4_OK;
       
  1533 
       
  1534     return MP4_NOT_STREAMABLE;
       
  1535   }
       
  1536 
       
  1537   /* There is video, but no audio */
       
  1538 
       
  1539   if (handle->videoSampleNum && !handle->audioSampleNum)
       
  1540   {
       
  1541     if (!handle->moov)
       
  1542       return MP4_ERROR;
       
  1543 
       
  1544     if (!handle->moov->trakVideo)
       
  1545       return MP4_ERROR;
       
  1546 
       
  1547     if (!handle->moov->trakVideo->mdia)
       
  1548       return MP4_ERROR;
       
  1549 
       
  1550     if (!handle->moov->trakVideo->mdia->minf)
       
  1551       return MP4_ERROR;
       
  1552 
       
  1553     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  1554       return MP4_ERROR;
       
  1555 
       
  1556     if (!handle->moov->trakVideo->mdia->minf->stbl->stco)
       
  1557       return MP4_ERROR;
       
  1558 
       
  1559     if (handle->moov->trakVideo->mdia->minf->stbl->stco->entryCount < 2)
       
  1560       return MP4_OK;
       
  1561 
       
  1562     if (getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 0) <
       
  1563         getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 1))
       
  1564       return MP4_OK;
       
  1565 
       
  1566     return MP4_NOT_STREAMABLE;
       
  1567   }
       
  1568 
       
  1569   /* There are both audio and video */
       
  1570 
       
  1571   if (handle->videoSampleNum && handle->audioSampleNum)
       
  1572   {
       
  1573     mp4_i64 diff;
       
  1574 
       
  1575 
       
  1576     if (!handle->moov)
       
  1577       return MP4_ERROR;
       
  1578 
       
  1579     if (!handle->moov->trakAudio)
       
  1580       return MP4_ERROR;
       
  1581 
       
  1582     if (!handle->moov->trakAudio->mdia)
       
  1583       return MP4_ERROR;
       
  1584 
       
  1585     if (!handle->moov->trakAudio->mdia->minf)
       
  1586       return MP4_ERROR;
       
  1587 
       
  1588     if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  1589       return MP4_ERROR;
       
  1590 
       
  1591     if (!handle->moov->trakAudio->mdia->minf->stbl->stco)
       
  1592       return MP4_ERROR;
       
  1593 
       
  1594     if (!handle->moov->trakAudio->mdia->minf->stbl->stco->entryCount)
       
  1595       return MP4_ERROR;
       
  1596 
       
  1597     if (!handle->moov->trakVideo)
       
  1598       return MP4_ERROR;
       
  1599 
       
  1600     if (!handle->moov->trakVideo->mdia)
       
  1601       return MP4_ERROR;
       
  1602 
       
  1603     if (!handle->moov->trakVideo->mdia->minf)
       
  1604       return MP4_ERROR;
       
  1605 
       
  1606     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  1607       return MP4_ERROR;
       
  1608 
       
  1609     if (!handle->moov->trakVideo->mdia->minf->stbl->stco)
       
  1610       return MP4_ERROR;
       
  1611 
       
  1612     if (!handle->moov->trakVideo->mdia->minf->stbl->stco->entryCount)
       
  1613       return MP4_ERROR;
       
  1614 
       
  1615     diff = getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 0) -
       
  1616            getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 0);
       
  1617 
       
  1618     /* If the distance between 1st audio and video chunk offsets is larger
       
  1619        than 50000, MP4 is not streamable. */
       
  1620 
       
  1621     if (diff < -50000 || diff > 50000)
       
  1622       return MP4_NOT_STREAMABLE;
       
  1623 
       
  1624     return MP4_OK;
       
  1625   }
       
  1626 
       
  1627   return MP4_OK;
       
  1628 }
       
  1629 
       
  1630 extern EXPORT_C MP4Err MP4ParseSeek(MP4Handle apihandle,
       
  1631                                                  mp4_u32 position,
       
  1632                                                  mp4_u32 *audioPosition,
       
  1633                                                  mp4_u32 *videoPosition,
       
  1634                                                  mp4_bool keyframe)
       
  1635 {
       
  1636   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1637   if (!handle->metaDataComplete)
       
  1638       {
       
  1639       switch (metaDataAvailable(handle))
       
  1640           {
       
  1641           case 0:
       
  1642               return MP4_NOT_AVAILABLE;
       
  1643           case 1:
       
  1644               handle->cafError = KErrNone;
       
  1645               if (readMetaData(handle) < 0)
       
  1646                   {
       
  1647 			      // Reading of meta data failed, so free up any allocated memory
       
  1648 		  		  freeFTYP(handle->ftyp);
       
  1649 		  		  handle->ftyp = NULL;
       
  1650 				  freeMOOV(handle->moov);
       
  1651 				  handle->moov = NULL;
       
  1652                   
       
  1653                   if ( handle->cafError != KErrNone )
       
  1654                       {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  1655                       return handle->cafError;
       
  1656                       }
       
  1657                   else
       
  1658                       {
       
  1659                       return MP4_INVALID_INPUT_STREAM;
       
  1660                       }
       
  1661                   }
       
  1662               handle->metaDataComplete = MP4TRUE;
       
  1663               break;
       
  1664 
       
  1665           case -2:
       
  1666             // Reading of FTYP meta data failed, so free up any allocated memory
       
  1667             freeFTYP(handle->ftyp);
       
  1668             handle->ftyp = NULL;
       
  1669             return MP4_ERROR;      
       
  1670 
       
  1671           case -1:
       
  1672           default:
       
  1673               return MP4_ERROR;
       
  1674           }
       
  1675       }
       
  1676 
       
  1677   if (!handle->moov)
       
  1678     return MP4_ERROR;
       
  1679 
       
  1680   handle->audioLast = MP4FALSE;
       
  1681   handle->videoLast = MP4FALSE;
       
  1682 
       
  1683   /* There is no audio nor video */
       
  1684 
       
  1685   if (!handle->audioSampleNum && !handle->videoSampleNum)
       
  1686     return MP4_ERROR;
       
  1687 
       
  1688   /* There is only audio */
       
  1689 
       
  1690   if (handle->audioSampleNum && !handle->videoSampleNum)
       
  1691   {
       
  1692     mp4_u32 audioSample;
       
  1693 
       
  1694     if (!handle->moov->trakAudio)
       
  1695       return MP4_ERROR;
       
  1696     if (!handle->moov->trakAudio->mdia)
       
  1697       return MP4_ERROR;
       
  1698 
       
  1699     if (convertTimeToSample(handle, handle->moov->trakAudio, position, &audioSample) < 0)
       
  1700       return MP4_CANT_SEEK;
       
  1701 
       
  1702     if (goToAudioSample(handle, handle->moov->trakAudio, audioSample) < 0)
       
  1703       return MP4_ERROR;
       
  1704 
       
  1705     if (convertAudioSampleToTime(handle, handle->moov->trakAudio->mdia, audioPosition, NULL) < 0)
       
  1706       return MP4_ERROR;
       
  1707     
       
  1708     if (handle->file)
       
  1709     	{
       
  1710     	handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
       
  1711     	}
       
  1712     else
       
  1713     	{
       
  1714     	// check if there is enough data in the buffers
       
  1715     	if (handle->audioSampleOffset + handle->audioSampleSize - 1 > getCumulativeBufferedBytes(handle))
       
  1716 	      	{
       
  1717 	      	if (handle->LastWriteDataCalled)
       
  1718 	      		{
       
  1719 	      		// user has indicated that no more data will be available
       
  1720 	      		return MP4_CANT_SEEK;	
       
  1721 	      		}
       
  1722 	      	else
       
  1723 		      	{
       
  1724 		      	// signal to user that more data needed
       
  1725 				return MP4_NOT_AVAILABLE;	
       
  1726 		      	}			
       
  1727 			}
       
  1728     	else if (handle->audioSampleOffset < handle->absPosition)
       
  1729     		{
       
  1730     		handle->absPosition = handle->audioSampleOffset;
       
  1731     		}    	
       
  1732     	}
       
  1733 
       
  1734     return MP4_OK;
       
  1735   	}
       
  1736 
       
  1737   	/* There is only video */
       
  1738   	if (handle->videoSampleNum && !handle->audioSampleNum)
       
  1739   		{
       
  1740   		mp4_u32 videoSample;
       
  1741   		mp4_u32 newVideoSample;
       
  1742 
       
  1743   		if (!handle->moov->trakVideo)
       
  1744   			return MP4_ERROR;
       
  1745   		if (!handle->moov->trakVideo->mdia)
       
  1746   			return MP4_ERROR;
       
  1747 
       
  1748   		if (convertTimeToSample(handle, handle->moov->trakVideo, position, &videoSample) < 0)
       
  1749   			return MP4_CANT_SEEK;
       
  1750 
       
  1751   		if (keyframe)
       
  1752   			{
       
  1753   			if (findVideoKeyFrame(handle, handle->moov->trakVideo, videoSample, &newVideoSample) < 0)
       
  1754   				{
       
  1755   				return MP4_CANT_SEEK;
       
  1756   				}
       
  1757   			videoSample = newVideoSample;
       
  1758   			}
       
  1759 
       
  1760   		if (goToVideoSample(handle, handle->moov->trakVideo, videoSample) < 0)
       
  1761   			{
       
  1762   			return MP4_ERROR;
       
  1763   			}
       
  1764 
       
  1765   		if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, videoPosition, NULL) < 0)
       
  1766   			{
       
  1767   			return MP4_ERROR;
       
  1768   			}
       
  1769 
       
  1770   		if (handle->file)
       
  1771   			{
       
  1772   			handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
       
  1773   			}
       
  1774   		else  // input is a stream
       
  1775   			{ 
       
  1776   			// check if there is enough data in the buffers
       
  1777   			if (handle->videoFrameOffset + handle->videoFrameSize > getCumulativeBufferedBytes(handle))
       
  1778   				{
       
  1779   		      	if (handle->LastWriteDataCalled)
       
  1780   		      		{
       
  1781   		      		// user has indicated that no more data will be available
       
  1782   		      		return MP4_CANT_SEEK;	
       
  1783   		      		}
       
  1784   		      	else
       
  1785   			      	{
       
  1786   			      	// signal to user that more data needed
       
  1787   					return MP4_NOT_AVAILABLE;	
       
  1788   			      	}			
       
  1789   				}
       
  1790   			else
       
  1791   				{
       
  1792   				handle->absPosition = handle->videoFrameOffset;
       
  1793   				}
       
  1794   			}
       
  1795 
       
  1796   		return MP4_OK;
       
  1797   		}
       
  1798 
       
  1799   /* There is audio and video */
       
  1800 
       
  1801   if (handle->videoSampleNum && handle->audioSampleNum)
       
  1802   {
       
  1803     mp4_u32 audioSample;
       
  1804     mp4_u32 videoSample;
       
  1805     mp4_u32 newVideoSample;
       
  1806 
       
  1807 
       
  1808     if (!handle->moov->trakAudio)
       
  1809       return MP4_ERROR;
       
  1810     if (!handle->moov->trakAudio->mdia)
       
  1811       return MP4_ERROR;
       
  1812     if (!handle->moov->trakVideo)
       
  1813       return MP4_ERROR;
       
  1814     if (!handle->moov->trakVideo->mdia)
       
  1815       return MP4_ERROR;
       
  1816 
       
  1817     if (convertTimeToSample(handle, handle->moov->trakVideo, position, &videoSample) < 0)
       
  1818       return MP4_CANT_SEEK;
       
  1819 
       
  1820     if (keyframe)
       
  1821     {
       
  1822       if (findVideoKeyFrame(handle, handle->moov->trakVideo, videoSample, &newVideoSample) < 0)
       
  1823         return MP4_CANT_SEEK;
       
  1824 
       
  1825       videoSample = newVideoSample;
       
  1826     }
       
  1827 
       
  1828     if (goToVideoSample(handle, handle->moov->trakVideo, videoSample) < 0)
       
  1829       return MP4_ERROR;
       
  1830 
       
  1831     if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, videoPosition, NULL) < 0)
       
  1832       return MP4_ERROR;
       
  1833 
       
  1834     if (handle->file)
       
  1835     	{
       
  1836     	handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;	
       
  1837     	}      
       
  1838     else  // input is a stream
       
  1839     	{	
       
  1840     	// check if there is enough data in the buffers
       
  1841 		if (handle->videoFrameOffset + handle->videoFrameSize > getCumulativeBufferedBytes(handle))
       
  1842 	      	{
       
  1843 	      	if (handle->LastWriteDataCalled)
       
  1844 	      		{
       
  1845 	      		// user has indicated that no more data will be available
       
  1846 	      		return MP4_CANT_SEEK;	
       
  1847 	      		}
       
  1848 	      	else
       
  1849 		      	{
       
  1850 		      	// signal to user that more data needed
       
  1851 				return MP4_NOT_AVAILABLE;	
       
  1852 		      	}			
       
  1853 	      	}        	
       
  1854 		else
       
  1855 	      	{
       
  1856 	        handle->absPosition = handle->videoFrameOffset;
       
  1857 	      	}        	
       
  1858     }
       
  1859 
       
  1860     /* Audio */
       
  1861 
       
  1862     if (convertTimeToSample(handle, handle->moov->trakAudio, *videoPosition, &audioSample) < 0)
       
  1863       return MP4_CANT_SEEK;
       
  1864 
       
  1865     if (goToAudioSample(handle, handle->moov->trakAudio, audioSample) < 0)
       
  1866       return MP4_ERROR;
       
  1867 
       
  1868     if (convertAudioSampleToTime(handle, handle->moov->trakAudio->mdia, audioPosition, NULL) < 0)
       
  1869       return MP4_ERROR;
       
  1870 
       
  1871     if (handle->file)  
       
  1872     	{
       
  1873 	      if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile)
       
  1874 	      	{
       
  1875 			handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;      	
       
  1876 	      	}        
       
  1877     	}
       
  1878     else   // input is a stream
       
  1879     	{
       
  1880     	// check if there is enough data in the buffers
       
  1881 		if (handle->audioSampleOffset + handle->audioSampleSize - 1 > getCumulativeBufferedBytes(handle))
       
  1882 			{
       
  1883 	      	if (handle->LastWriteDataCalled)
       
  1884 	      		{
       
  1885 	      		// user has indicated that no more data will be available
       
  1886 	      		return MP4_CANT_SEEK;	
       
  1887 	      		}
       
  1888 	      	else
       
  1889 		      	{
       
  1890 		      	// signal to user that more data needed
       
  1891 				return MP4_NOT_AVAILABLE;	
       
  1892 		      	}
       
  1893 			}
       
  1894 		else if (handle->audioSampleOffset < handle->absPosition)
       
  1895 			{
       
  1896 			handle->absPosition = handle->audioSampleOffset;
       
  1897 			}
       
  1898 		}
       
  1899 
       
  1900     return MP4_OK;
       
  1901   }
       
  1902 
       
  1903   return MP4_OK;
       
  1904 }
       
  1905 
       
  1906 extern EXPORT_C MP4Err MP4ParseIsFrameAvailable(MP4Handle apihandle,
       
  1907                                                              mp4_u32 type)
       
  1908 {
       
  1909     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  1910     if (!handle->metaDataComplete)
       
  1911         {
       
  1912         switch (metaDataAvailable(handle))
       
  1913             {
       
  1914             case 0:
       
  1915                 return MP4_NOT_AVAILABLE;
       
  1916             case 1:
       
  1917                 handle->cafError = KErrNone;
       
  1918                 if (readMetaData(handle) < 0)
       
  1919                     {
       
  1920 			      	// Reading of meta data failed, so free up any allocated memory
       
  1921 			  		freeFTYP(handle->ftyp);
       
  1922 			  		handle->ftyp = NULL;
       
  1923 					freeMOOV(handle->moov);
       
  1924 					handle->moov = NULL;
       
  1925                     
       
  1926                   	if ( handle->cafError != KErrNone )
       
  1927                       	{
       
  1928 						// if CAF/DRM caused the error return it instead of generic errorcode.
       
  1929 
       
  1930                       	return handle->cafError;
       
  1931                      	}
       
  1932                   	else
       
  1933                       	{
       
  1934                         return MP4_INVALID_INPUT_STREAM;
       
  1935                    	    }
       
  1936                     }
       
  1937                 handle->metaDataComplete = MP4TRUE;
       
  1938                 break;
       
  1939 
       
  1940             case -2:
       
  1941               // Reading of FTYP meta data failed, so free up any allocated memory
       
  1942               freeFTYP(handle->ftyp);
       
  1943               handle->ftyp = NULL;
       
  1944               return MP4_ERROR;      
       
  1945 
       
  1946             case -1:
       
  1947             default:
       
  1948                 return MP4_ERROR;
       
  1949             }
       
  1950         }
       
  1951 
       
  1952   switch (type & handle->type)
       
  1953   {
       
  1954   case MP4_TYPE_MPEG4_VIDEO:
       
  1955   case MP4_TYPE_H263_PROFILE_0:
       
  1956   case MP4_TYPE_H263_PROFILE_3:
       
  1957   case MP4_TYPE_AVC_PROFILE_BASELINE:
       
  1958   case MP4_TYPE_AVC_PROFILE_MAIN:
       
  1959   case MP4_TYPE_AVC_PROFILE_EXTENDED:
       
  1960   case MP4_TYPE_AVC_PROFILE_HIGH:
       
  1961 
       
  1962     /* There is no frame available if last sample has been reached */
       
  1963 
       
  1964     if (handle->videoLast)
       
  1965       return MP4_NO_REQUESTED_FRAME;
       
  1966 
       
  1967     /* Input in a file => it is available */
       
  1968 
       
  1969     if (handle->file)
       
  1970       return MP4_OK;
       
  1971 
       
  1972     /* If frame has been buffered, it is available */
       
  1973 
       
  1974     if (handle->videoFrameOffset + handle->videoFrameSize <=
       
  1975         getCumulativeBufferedBytes(handle))
       
  1976       return MP4_OK;
       
  1977     else
       
  1978       return MP4_NOT_AVAILABLE;
       
  1979 
       
  1980   case MP4_TYPE_MPEG4_AUDIO:
       
  1981   case MP4_TYPE_AMR_NB:
       
  1982   case MP4_TYPE_AMR_WB:
       
  1983   case MP4_TYPE_QCELP_13K:
       
  1984 
       
  1985     /* There is no frame available if last sample has been reached */
       
  1986 
       
  1987     if (handle->audioLast)
       
  1988       return MP4_NO_REQUESTED_FRAME;
       
  1989 
       
  1990     /* Input in a file => it is available */
       
  1991 
       
  1992     if (handle->file)
       
  1993       return MP4_OK;
       
  1994 
       
  1995     /* If frame has been buffered, it is available */
       
  1996 
       
  1997     if (handle->audioSampleOffset + handle->audioSampleSize <=
       
  1998         getCumulativeBufferedBytes(handle))
       
  1999       return MP4_OK;
       
  2000     else
       
  2001       return MP4_NOT_AVAILABLE;
       
  2002 
       
  2003   case MP4_TYPE_NONE:
       
  2004   default:
       
  2005 
       
  2006     return MP4_NO_REQUESTED_FRAME;
       
  2007   }
       
  2008 }
       
  2009 
       
  2010 extern EXPORT_C MP4Err MP4ParseGetLastPosition(MP4Handle apihandle,
       
  2011                                                             mp4_u32 *position)
       
  2012 {
       
  2013   return MP4ParseGetLastPosition64(apihandle, (mp4_u64 *)position);
       
  2014 }
       
  2015 
       
  2016 extern EXPORT_C MP4Err MP4ParseGetLastPosition64(MP4Handle apihandle,
       
  2017                                                             mp4_u64 *position)
       
  2018 {
       
  2019   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2020   if (!handle->file)
       
  2021       {
       
  2022       *position = handle->absPosition; // return the latest accessed absolute byte location of the stream.
       
  2023       return MP4_OK;
       
  2024       }
       
  2025   *position = handle->lastAccessedPosInFile;
       
  2026 
       
  2027   return MP4_OK;
       
  2028 }
       
  2029 
       
  2030 extern EXPORT_C MP4Err MP4ParseGetNumberOfVideoFrames(MP4Handle apihandle, 
       
  2031                                                                    mp4_u32 *numberOfFrames)
       
  2032 {
       
  2033   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2034   if (!handle->metaDataComplete)
       
  2035       {
       
  2036       switch (metaDataAvailable(handle))
       
  2037           {
       
  2038           case 0:
       
  2039               return MP4_NOT_AVAILABLE;
       
  2040           case 1:
       
  2041               handle->cafError = KErrNone;
       
  2042               if (readMetaData(handle) < 0)
       
  2043                   {
       
  2044 			      // Reading of meta data failed, so free up any allocated memory
       
  2045 		  		  freeFTYP(handle->ftyp);
       
  2046 		  		  handle->ftyp = NULL;
       
  2047 				  freeMOOV(handle->moov);
       
  2048 			 	  handle->moov = NULL;
       
  2049                   
       
  2050                   if ( handle->cafError != KErrNone )
       
  2051                       {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2052                       return handle->cafError;
       
  2053                       }
       
  2054                   else
       
  2055                       {
       
  2056                       return MP4_INVALID_INPUT_STREAM;
       
  2057                       }
       
  2058                   }
       
  2059               handle->metaDataComplete = MP4TRUE;
       
  2060               break;
       
  2061 
       
  2062           case -2:
       
  2063             // Reading of FTYP meta data failed, so free up any allocated memory
       
  2064             freeFTYP(handle->ftyp);
       
  2065             handle->ftyp = NULL;
       
  2066             return MP4_ERROR;      
       
  2067 
       
  2068           case -1:
       
  2069           default:
       
  2070               return MP4_ERROR;
       
  2071           }
       
  2072       }
       
  2073   
       
  2074   if (!handle->moov)
       
  2075     return MP4_ERROR;
       
  2076 
       
  2077   if (handle->moov->trakVideo)
       
  2078   {
       
  2079     if (!handle->moov->trakVideo->mdia)
       
  2080       return MP4_ERROR;
       
  2081 
       
  2082     if (!handle->moov->trakVideo->mdia->minf)
       
  2083       return MP4_ERROR;
       
  2084 
       
  2085     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2086       return MP4_ERROR;
       
  2087 
       
  2088     if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
       
  2089       return MP4_ERROR;
       
  2090    }
       
  2091    else
       
  2092    {
       
  2093       return MP4_ERROR;
       
  2094    }
       
  2095 
       
  2096    *numberOfFrames = handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount;
       
  2097    return MP4_OK;
       
  2098 }
       
  2099 
       
  2100 extern EXPORT_C MP4Err MP4ParseGetVideoFrameSize(MP4Handle apihandle, 
       
  2101                                                               mp4_u32 index, 
       
  2102                                                               mp4_u32 *frameSize)
       
  2103 	{
       
  2104 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2105 	if (!handle->metaDataComplete)
       
  2106 		{
       
  2107 		switch (metaDataAvailable(handle))
       
  2108 			{
       
  2109 			case 0:
       
  2110 				return MP4_NOT_AVAILABLE;
       
  2111 			case 1:
       
  2112 				handle->cafError = KErrNone;
       
  2113 				if (readMetaData(handle) < 0)
       
  2114 					{
       
  2115 			      	// Reading of meta data failed, so free up any allocated memory
       
  2116 			  		freeFTYP(handle->ftyp);
       
  2117 			  		handle->ftyp = NULL;
       
  2118 					freeMOOV(handle->moov);
       
  2119 					handle->moov = NULL;
       
  2120 
       
  2121 					if ( handle->cafError != KErrNone )
       
  2122 						{// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2123 						return handle->cafError;
       
  2124 						}
       
  2125 					else
       
  2126 						{
       
  2127 						return MP4_INVALID_INPUT_STREAM;
       
  2128 						}
       
  2129 					}
       
  2130 				handle->metaDataComplete = MP4TRUE;
       
  2131 				break;
       
  2132 
       
  2133 		    case -2:
       
  2134 		      // Reading of FTYP meta data failed, so free up any allocated memory
       
  2135 		      freeFTYP(handle->ftyp);
       
  2136 		      handle->ftyp = NULL;
       
  2137 		      return MP4_ERROR;      
       
  2138 
       
  2139 			case -1:
       
  2140 			default:
       
  2141 				return MP4_ERROR;
       
  2142 			}
       
  2143 		}
       
  2144 
       
  2145 	if (!handle->moov)
       
  2146 		return MP4_ERROR;
       
  2147 
       
  2148 	if (handle->moov->trakVideo)
       
  2149 		{
       
  2150 	    if (!handle->moov->trakVideo->mdia)
       
  2151 	    	return MP4_ERROR;
       
  2152 	
       
  2153 	    if (!handle->moov->trakVideo->mdia->minf)
       
  2154 	    	return MP4_ERROR;
       
  2155 	
       
  2156 	    if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2157 	    	return MP4_ERROR;
       
  2158 	
       
  2159 	    if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
       
  2160 	    	return MP4_ERROR;
       
  2161 	    
       
  2162 	    // ensure the index entered is within bound
       
  2163 	    if (index >= handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount)
       
  2164 	    	return MP4_ERROR;     	
       
  2165 		}
       
  2166 	else
       
  2167 		{
       
  2168 		return MP4_ERROR;
       
  2169 		}
       
  2170 
       
  2171 	*frameSize = handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[index];
       
  2172 	return MP4_OK;
       
  2173 	}
       
  2174 
       
  2175 extern EXPORT_C MP4Err MP4ParseGetVideoFrameStartTime(MP4Handle apihandle, 
       
  2176                                                                    mp4_u32 index, 
       
  2177                                                                    mp4_u32 *timestamp,
       
  2178                                                                    mp4_u32 *timestampms)
       
  2179 {
       
  2180   mp4_u32      tmptime=0;
       
  2181   mp4_u32      sample=0;
       
  2182   mp4_u32      entry=0;
       
  2183   mp4_u32      videoSampleNumber = index+1;
       
  2184 
       
  2185   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2186   if (!handle->metaDataComplete)
       
  2187       {
       
  2188       switch (metaDataAvailable(handle))
       
  2189           {
       
  2190           case 0:
       
  2191               return MP4_NOT_AVAILABLE;
       
  2192           case 1:
       
  2193               handle->cafError = KErrNone;
       
  2194               if (readMetaData(handle) < 0)
       
  2195                   {
       
  2196 		      	  // Reading of meta data failed, so free up any allocated memory
       
  2197 		  		  freeFTYP(handle->ftyp);
       
  2198 		  		  handle->ftyp = NULL;
       
  2199 				  freeMOOV(handle->moov);
       
  2200 				  handle->moov = NULL;
       
  2201                   
       
  2202                   if ( handle->cafError != KErrNone )
       
  2203                       {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2204                       return handle->cafError;
       
  2205                       }
       
  2206                   else
       
  2207                       {
       
  2208                       return MP4_INVALID_INPUT_STREAM;
       
  2209                       }
       
  2210                   }
       
  2211               handle->metaDataComplete = MP4TRUE;
       
  2212               break;
       
  2213 
       
  2214           case -2:
       
  2215             // Reading of FTYP meta data failed, so free up any allocated memory
       
  2216             freeFTYP(handle->ftyp);
       
  2217             handle->ftyp = NULL;
       
  2218             return MP4_ERROR;      
       
  2219 
       
  2220           case -1:
       
  2221           default:
       
  2222               return MP4_ERROR;
       
  2223           }
       
  2224       }  
       
  2225 
       
  2226   if (!handle->moov)
       
  2227   {
       
  2228     return MP4_ERROR;
       
  2229   }
       
  2230 
       
  2231   if (handle->moov->trakVideo)
       
  2232   {
       
  2233     if (!handle->moov->trakVideo->mdia)
       
  2234       return MP4_ERROR;
       
  2235 
       
  2236     if (!handle->moov->trakVideo->mdia->minf)
       
  2237       return MP4_ERROR;
       
  2238 
       
  2239     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2240       return MP4_ERROR;
       
  2241 
       
  2242     if (!handle->moov->trakVideo->mdia->minf->stbl->stts)
       
  2243       return MP4_ERROR;
       
  2244   }
       
  2245   else
       
  2246   {
       
  2247     return MP4_ERROR;
       
  2248   }
       
  2249 
       
  2250   for (;;)
       
  2251   {
       
  2252     if (sample + handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry] < videoSampleNumber)
       
  2253     {
       
  2254       sample += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];
       
  2255       tmptime += (handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry] * 
       
  2256 				handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry]);
       
  2257       entry++;
       
  2258       if (entry == handle->moov->trakVideo->mdia->minf->stbl->stts->entryCount)
       
  2259         return MP4_ERROR;
       
  2260     }
       
  2261     else
       
  2262     {
       
  2263       tmptime += ((videoSampleNumber - sample - 1) * handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry]);
       
  2264       break;
       
  2265     }
       
  2266   }
       
  2267   if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
       
  2268     {
       
  2269     return MP4_ERROR;
       
  2270     }
       
  2271   
       
  2272   *timestamp = tmptime;
       
  2273 
       
  2274   *timestampms =(mp4_u32)((mp4_double)tmptime * (mp4_double)1000 / 
       
  2275                                (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale + (mp4_double)0.5);
       
  2276 
       
  2277   return MP4_OK;
       
  2278 }
       
  2279 
       
  2280 extern EXPORT_C MP4Err MP4ParseGetVideoFrameType(MP4Handle apihandle, 
       
  2281                                                               mp4_u32 index, 
       
  2282                                                               mp4_bool *frametype)
       
  2283 	{
       
  2284 	mp4_u32  i;
       
  2285 	mp4_u32  videoSampleNumber = index+1;
       
  2286 	mp4_bool keyFrame = MP4FALSE;
       
  2287 
       
  2288   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2289   if (!handle->metaDataComplete)
       
  2290       {
       
  2291       switch (metaDataAvailable(handle))
       
  2292           {
       
  2293           case 0:
       
  2294               return MP4_NOT_AVAILABLE;
       
  2295           case 1:
       
  2296               handle->cafError = KErrNone;
       
  2297               if (readMetaData(handle) < 0)
       
  2298                   {
       
  2299 		      	  // Reading of meta data failed, so free up any allocated memory
       
  2300 		  		  freeFTYP(handle->ftyp);
       
  2301 		  		  handle->ftyp = NULL;
       
  2302 				  freeMOOV(handle->moov);
       
  2303 				  handle->moov = NULL;
       
  2304                   
       
  2305                   if ( handle->cafError != KErrNone )
       
  2306                       {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2307                       return handle->cafError;
       
  2308                       }
       
  2309                   else
       
  2310                       {
       
  2311                       return MP4_INVALID_INPUT_STREAM;
       
  2312                       }
       
  2313                   }
       
  2314               handle->metaDataComplete = MP4TRUE;
       
  2315               break;
       
  2316 
       
  2317           case -2:
       
  2318             // Reading of FTYP meta data failed, so free up any allocated memory
       
  2319             freeFTYP(handle->ftyp);
       
  2320             handle->ftyp = NULL;
       
  2321             return MP4_ERROR;      
       
  2322 
       
  2323           case -1:
       
  2324           default:
       
  2325               return MP4_ERROR;
       
  2326           }
       
  2327       }  
       
  2328 
       
  2329 	if (!handle->moov)
       
  2330 		return MP4_ERROR;
       
  2331 
       
  2332 	if (handle->moov->trakVideo)
       
  2333 		{
       
  2334 		if (!handle->moov->trakVideo->mdia)
       
  2335 			return MP4_ERROR;
       
  2336 
       
  2337 		if (!handle->moov->trakVideo->mdia->minf)
       
  2338 			return MP4_ERROR;
       
  2339 		
       
  2340 		if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2341 			return MP4_ERROR;
       
  2342 		
       
  2343 		if (!handle->moov->trakVideo->mdia->minf->stbl->stss)
       
  2344 			return MP4_ERROR;
       
  2345 
       
  2346 		// if the video frame index is out of bounds
       
  2347 		if (!handle->moov->trakVideo->mdia->minf->stbl->stsz ||
       
  2348 			videoSampleNumber > handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount)
       
  2349 			return MP4_ERROR;
       
  2350 		}
       
  2351   	else
       
  2352   		{
       
  2353   		return MP4_ERROR;
       
  2354   		}
       
  2355 
       
  2356 	for (i=0; i < handle->moov->trakVideo->mdia->minf->stbl->stss->entryCount; i++)
       
  2357 		{
       
  2358     	if (handle->moov->trakVideo->mdia->minf->stbl->stss->sampleNumber[i] == videoSampleNumber)
       
  2359 			{
       
  2360 			keyFrame = MP4TRUE;
       
  2361 			break;
       
  2362 	    	}
       
  2363   		}
       
  2364   
       
  2365 	*frametype = keyFrame;
       
  2366   	return MP4_OK;
       
  2367 }
       
  2368 
       
  2369 extern EXPORT_C MP4Err MP4ParseGetVideoSampleEntryIndex(MP4Handle apihandle, mp4_u32 *videosampleentryindex)
       
  2370 {
       
  2371     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2372     if (!handle->metaDataComplete)
       
  2373         {
       
  2374         switch (metaDataAvailable(handle))
       
  2375             {
       
  2376             case 0:
       
  2377                 return MP4_NOT_AVAILABLE;
       
  2378             case 1:
       
  2379                 handle->cafError = KErrNone;
       
  2380                 if (readMetaData(handle) < 0)
       
  2381                     {
       
  2382 			      	// Reading of meta data failed, so free up any allocated memory
       
  2383 			  		freeFTYP(handle->ftyp);
       
  2384 			  		handle->ftyp = NULL;
       
  2385 					freeMOOV(handle->moov);
       
  2386 					handle->moov = NULL;
       
  2387                     
       
  2388                     if ( handle->cafError != KErrNone )
       
  2389                         {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2390                         return handle->cafError;
       
  2391                         }
       
  2392                     else
       
  2393                         {
       
  2394                         return MP4_INVALID_INPUT_STREAM;
       
  2395                         }
       
  2396                     }
       
  2397                 handle->metaDataComplete = MP4TRUE;
       
  2398                 break;
       
  2399 
       
  2400             case -2:
       
  2401               // Reading of FTYP meta data failed, so free up any allocated memory
       
  2402               freeFTYP(handle->ftyp);
       
  2403               handle->ftyp = NULL;
       
  2404               return MP4_ERROR;      
       
  2405 
       
  2406             case -1:
       
  2407             default:
       
  2408                 return MP4_ERROR;
       
  2409             }
       
  2410         }    
       
  2411 
       
  2412     if (!handle->moov->trakVideo)
       
  2413       return MP4_ERROR;
       
  2414     if (!handle->moov->trakVideo->mdia)
       
  2415       return MP4_ERROR;
       
  2416 
       
  2417 	if (handle->videoSampleEntryIndex == 0) /* can't be zero. Sample Entry index must be at least 1*/
       
  2418 		return MP4_ERROR;
       
  2419 	else
       
  2420 		*videosampleentryindex = handle->videoSampleEntryIndex;
       
  2421 
       
  2422 	return MP4_OK;
       
  2423 }
       
  2424 
       
  2425 extern EXPORT_C MP4Err MP4ParseGetAudioSampleEntryIndex(MP4Handle apihandle, mp4_u32 *audiosampleentryindex)
       
  2426 {
       
  2427     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2428     if (!handle->metaDataComplete)
       
  2429         {
       
  2430         switch (metaDataAvailable(handle))
       
  2431             {
       
  2432             case 0:
       
  2433                 return MP4_NOT_AVAILABLE;
       
  2434             case 1:
       
  2435                 handle->cafError = KErrNone;
       
  2436                 if (readMetaData(handle) < 0)
       
  2437                     {
       
  2438       				// Reading of meta data failed, so free up any allocated memory
       
  2439 			  		freeFTYP(handle->ftyp);
       
  2440 			  		handle->ftyp = NULL;
       
  2441 					freeMOOV(handle->moov);
       
  2442 					handle->moov = NULL;
       
  2443                     
       
  2444                     if ( handle->cafError != KErrNone )
       
  2445                         {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2446                         return handle->cafError;
       
  2447                         }
       
  2448                     else
       
  2449                         {
       
  2450                         return MP4_INVALID_INPUT_STREAM;
       
  2451                         }
       
  2452                     }
       
  2453                 handle->metaDataComplete = MP4TRUE;
       
  2454                 break;
       
  2455 
       
  2456             case -2:
       
  2457               // Reading of FTYP meta data failed, so free up any allocated memory
       
  2458               freeFTYP(handle->ftyp);
       
  2459               handle->ftyp = NULL;
       
  2460               return MP4_ERROR;      
       
  2461 
       
  2462             case -1:
       
  2463             default:
       
  2464                 return MP4_ERROR;
       
  2465             }
       
  2466         }    
       
  2467 
       
  2468     if (!handle->moov->trakAudio)
       
  2469       return MP4_ERROR;
       
  2470     if (!handle->moov->trakAudio->mdia)
       
  2471       return MP4_ERROR;
       
  2472 
       
  2473 	if (handle->audioSampleEntryIndex == 0) /* can't be zero. Sample Entry index must be at least 1*/
       
  2474 		return MP4_ERROR;
       
  2475 	else
       
  2476 		*audiosampleentryindex = handle->audioSampleEntryIndex;
       
  2477 
       
  2478 	return MP4_OK;
       
  2479 }
       
  2480 
       
  2481 extern EXPORT_C MP4Err MP4ParseGetQCELPStorageMode(MP4Handle apihandle, mp4_u8 *qcelpStorageMode)
       
  2482 {
       
  2483     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2484     if (!handle->metaDataComplete)
       
  2485         {
       
  2486         switch (metaDataAvailable(handle))
       
  2487             {
       
  2488             case 0:
       
  2489                 return MP4_NOT_AVAILABLE;
       
  2490             case 1:
       
  2491                 handle->cafError = KErrNone;
       
  2492                 if (readMetaData(handle) < 0)
       
  2493                     {
       
  2494 			      	// Reading of meta data failed, so free up any allocated memory
       
  2495 			  		freeFTYP(handle->ftyp);
       
  2496 			  		handle->ftyp = NULL;
       
  2497 					freeMOOV(handle->moov);
       
  2498 					handle->moov = NULL;
       
  2499                     
       
  2500                     if ( handle->cafError != KErrNone )
       
  2501                         {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2502                         return handle->cafError;
       
  2503                         }
       
  2504                     else
       
  2505                         {
       
  2506                         return MP4_INVALID_INPUT_STREAM;
       
  2507                         }
       
  2508                     }
       
  2509                 handle->metaDataComplete = MP4TRUE;
       
  2510                 break;
       
  2511 
       
  2512             case -2:
       
  2513               // Reading of FTYP meta data failed, so free up any allocated memory
       
  2514               freeFTYP(handle->ftyp);
       
  2515               handle->ftyp = NULL;
       
  2516               return MP4_ERROR;      
       
  2517 
       
  2518             case -1:
       
  2519             default:
       
  2520                 return MP4_ERROR;
       
  2521             }
       
  2522         }    
       
  2523 
       
  2524     if (!handle->moov->trakAudio)
       
  2525       return MP4_ERROR;
       
  2526     if (!handle->moov->trakAudio->mdia)
       
  2527       return MP4_ERROR;
       
  2528     if (!(handle->type & MP4_TYPE_QCELP_13K))
       
  2529       return MP4_ERROR;
       
  2530 
       
  2531     if(handle->qcelpStoredAsMPEGAudio)
       
  2532        *qcelpStorageMode = 1;
       
  2533     else
       
  2534       *qcelpStorageMode = 0;
       
  2535 
       
  2536     return MP4_OK;
       
  2537 }
       
  2538 
       
  2539 extern EXPORT_C MP4Err MP4GetVideoFrameProperties(MP4Handle apihandle,mp4_u32 startindex,mp4_u32 sizeofarray,TFrameInfoParameters* aFrameInfoArray)
       
  2540 {
       
  2541 
       
  2542 	mp4_u32      tmptime=0;
       
  2543 	mp4_u32      sample=0;
       
  2544 	mp4_u32      entry=0;
       
  2545 	mp4_u32      videoSampleNumber = (startindex+sizeofarray)+1;
       
  2546 	mp4_u32  i;
       
  2547 	mp4_u32  j;
       
  2548 	mp4_u32  index;
       
  2549 	mp4_u32  actualIndex;
       
  2550 
       
  2551 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2552 	
       
  2553 	TBool sampleSyncTableExists = ETrue;
       
  2554 	  if (!handle->metaDataComplete)
       
  2555 	      {
       
  2556 	      switch (metaDataAvailable(handle))
       
  2557 	          {
       
  2558 	          case 0:
       
  2559 	              return MP4_NOT_AVAILABLE;
       
  2560 	          case 1:
       
  2561 	              handle->cafError = KErrNone;
       
  2562 	              if (readMetaData(handle) < 0)
       
  2563 	                  {
       
  2564 			      	  // Reading of meta data failed, so free up any allocated memory
       
  2565 			  		  freeFTYP(handle->ftyp);
       
  2566 			  		  handle->ftyp = NULL;
       
  2567 					  freeMOOV(handle->moov);
       
  2568 					  handle->moov = NULL;
       
  2569 	                  
       
  2570 	                  if ( handle->cafError != KErrNone )
       
  2571 	                      {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2572 	                      return handle->cafError;
       
  2573 	                      }
       
  2574 	                  else
       
  2575 	                      {
       
  2576 	                      return MP4_INVALID_INPUT_STREAM;
       
  2577 	                      }
       
  2578 	                  }
       
  2579 	              handle->metaDataComplete = MP4TRUE;
       
  2580 	              break;
       
  2581 
       
  2582 	          case -2:
       
  2583 	            // Reading of FTYP meta data failed, so free up any allocated memory
       
  2584 	            freeFTYP(handle->ftyp);
       
  2585 	            handle->ftyp = NULL;
       
  2586 	            return MP4_ERROR;      
       
  2587 
       
  2588 	          case -1:
       
  2589 	          default:
       
  2590 	              return MP4_ERROR;
       
  2591 	          }
       
  2592 	      }	
       
  2593 
       
  2594 
       
  2595 	if (!handle->moov)
       
  2596 		return MP4_ERROR;
       
  2597 
       
  2598   	if (handle->moov->trakVideo)
       
  2599 	  	{
       
  2600 		if (!handle->moov->trakVideo->mdia)
       
  2601 		  	return MP4_ERROR;
       
  2602 
       
  2603 		if (!handle->moov->trakVideo->mdia->minf)
       
  2604 		  	return MP4_ERROR;
       
  2605 
       
  2606 		if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2607 		  	return MP4_ERROR;
       
  2608 
       
  2609 		if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)	//for size
       
  2610 		  	return MP4_ERROR;
       
  2611 		  
       
  2612 		if (!handle->moov->trakVideo->mdia->minf->stbl->stss)	//for type
       
  2613 			{
       
  2614 			// If sample sync table doesn't exist mark all frames as intra / random access point			
       
  2615 			sampleSyncTableExists = EFalse;
       
  2616 			}
       
  2617 		
       
  2618 		if (!handle->moov->trakVideo->mdia->minf->stbl->stts)	//For timeStamp
       
  2619 			return MP4_ERROR;
       
  2620 	  	}
       
  2621 	  else
       
  2622 		{
       
  2623 		return MP4_ERROR;
       
  2624 		}
       
  2625 
       
  2626 
       
  2627 	if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)	//For timeStamp
       
  2628     {
       
  2629 		 return MP4_ERROR;
       
  2630     }
       
  2631 
       
  2632 	if((startindex+sizeofarray) > handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount)	//more than number of frames
       
  2633 	{
       
  2634 		 return MP4_ERROR;	
       
  2635 	}
       
  2636 
       
  2637 	if(aFrameInfoArray == NULL)
       
  2638 	{
       
  2639 		return MP4_NO_OUTPUT_BUFFER;
       
  2640 	}
       
  2641 
       
  2642 	if ( sampleSyncTableExists )
       
  2643 		{
       
  2644 		for (i=0; i < handle->moov->trakVideo->mdia->minf->stbl->stss->entryCount; i++)		//set all types to true
       
  2645 			{
       
  2646 			//because counting is stored from 1 but index from 0
       
  2647 			mp4_u32 currFrame = handle->moov->trakVideo->mdia->minf->stbl->stss->sampleNumber[i] - 1;	
       
  2648 			
       
  2649 			if ((currFrame >= startindex) && (currFrame < (startindex + sizeofarray)))
       
  2650 				{
       
  2651 				aFrameInfoArray[currFrame - startindex].iType = MP4TRUE;							
       
  2652 				}
       
  2653 			}
       
  2654 	  	}
       
  2655 
       
  2656     index=0;	//initialize to beginning
       
  2657 	actualIndex=0;//array indexer
       
  2658 
       
  2659 	for(;;)
       
  2660 		{
       
  2661 		if(index< videoSampleNumber)
       
  2662 			{
       
  2663 			for(j=0;j<handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];j++)
       
  2664 				{
       
  2665 				if(index >=startindex)
       
  2666 					{
       
  2667 					//first initialize flag to false if not previously set to true.
       
  2668 					if(aFrameInfoArray[actualIndex].iType != MP4TRUE)
       
  2669 						{
       
  2670 						aFrameInfoArray[actualIndex].iType = MP4FALSE;
       
  2671 						}
       
  2672 					//aFrameInfoArray[index].iStartTime = tmptime + handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry];
       
  2673 					if(index==0)		//so first frame of entire clip
       
  2674 						{
       
  2675 						aFrameInfoArray[actualIndex].iStartTime =0;
       
  2676 						}
       
  2677 					else
       
  2678 						{
       
  2679 					  	aFrameInfoArray[actualIndex].iStartTime = (mp4_u32)((mp4_double)tmptime * (mp4_double)1000 / 
       
  2680 	                           (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale + (mp4_double)0.5);
       
  2681 						}
       
  2682 					aFrameInfoArray[actualIndex].iSize = handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[index];
       
  2683 					// If sample sync table doesn't exist mark all frames as intra / random access point
       
  2684 					if (!sampleSyncTableExists)
       
  2685 						{
       
  2686 						aFrameInfoArray[actualIndex].iType = MP4TRUE;	
       
  2687 						}
       
  2688 					actualIndex++; //point to next index in array
       
  2689 					}
       
  2690 				tmptime += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry];
       
  2691 				//Now insert size before incrementing index
       
  2692 				if(index == videoSampleNumber-2)
       
  2693 				break;
       
  2694 				index++;
       
  2695 				}
       
  2696 			if(index==videoSampleNumber-2)
       
  2697 			break;
       
  2698 			sample += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];
       
  2699 			entry++;
       
  2700 			}
       
  2701 		else
       
  2702 			{
       
  2703 			break;
       
  2704 			}
       
  2705 		}
       
  2706 	return MP4_OK;
       
  2707 }
       
  2708 
       
  2709 extern EXPORT_C MP4Err MP4ParseGetVideoClipProperties(MP4Handle apihandle, TVideoClipProperties& aVideoClipProperties)
       
  2710 {
       
  2711     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2712     if (!handle)
       
  2713     	{
       
  2714         return MP4_ERROR;
       
  2715     	}
       
  2716     
       
  2717     if (!handle->metaDataComplete)
       
  2718         {
       
  2719         switch (metaDataAvailable(handle))
       
  2720             {
       
  2721             case 0:
       
  2722                 return MP4_NOT_AVAILABLE;
       
  2723             case 1:
       
  2724                 handle->cafError = KErrNone;
       
  2725                 if (readMetaData(handle) < 0)
       
  2726                     {
       
  2727       				// Reading of meta data failed, so free up any allocated memory
       
  2728 			  		freeFTYP(handle->ftyp);
       
  2729 			  		handle->ftyp = NULL;
       
  2730 					freeMOOV(handle->moov);
       
  2731 					handle->moov = NULL;
       
  2732                     
       
  2733                     if ( handle->cafError != KErrNone )
       
  2734                         {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2735                         return handle->cafError;
       
  2736                         }
       
  2737                     else
       
  2738                         {
       
  2739                         return MP4_INVALID_INPUT_STREAM;
       
  2740                         }
       
  2741                     }
       
  2742                 handle->metaDataComplete = MP4TRUE;
       
  2743                 break;
       
  2744 
       
  2745             case -2:
       
  2746               // Reading of FTYP meta data failed, so free up any allocated memory
       
  2747               freeFTYP(handle->ftyp);
       
  2748               handle->ftyp = NULL;
       
  2749               return MP4_ERROR;      
       
  2750 
       
  2751             case -1:
       
  2752             default:
       
  2753                 return MP4_ERROR;
       
  2754             }
       
  2755         }    
       
  2756 
       
  2757     if (!handle->moov)
       
  2758         return MP4_ERROR;
       
  2759     if (!handle->moov->trakVideo)
       
  2760         return MP4_ERROR;
       
  2761     if (!handle->moov->trakVideo->mdia)
       
  2762         return MP4_ERROR;
       
  2763     if (!handle->moov->trakVideo->mdia->minf)
       
  2764         return MP4_ERROR;
       
  2765     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  2766         return MP4_ERROR;
       
  2767     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
       
  2768         return MP4_ERROR;
       
  2769 
       
  2770     /* Assume that the video type is the same for all sample entries. Just get the video type from the first one */
       
  2771     if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
       
  2772     {
       
  2773         if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263)
       
  2774             return MP4_ERROR;
       
  2775 
       
  2776         if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Level)
       
  2777         {
       
  2778             aVideoClipProperties.iH263Level = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Level;
       
  2779             return MP4_OK;
       
  2780         }
       
  2781         else
       
  2782         {
       
  2783             return MP4_ERROR;
       
  2784         }
       
  2785     }
       
  2786     else
       
  2787     {
       
  2788         return MP4_ERROR;        
       
  2789     }
       
  2790 }
       
  2791 
       
  2792 extern EXPORT_C MP4Err MP4ParseGetUserDataAtom(MP4Handle apihandle, 
       
  2793                                                             mp4_u8& udtaLocation,
       
  2794                                                             mp4_u32 udtaAtomType,
       
  2795                                                             mp4_u8* buffer,
       
  2796                                                             mp4_u32& bufferSize,
       
  2797                                                             mp4_u32& atomIndex )
       
  2798     {
       
  2799     mp4_u32 size = 0;
       
  2800     mp4_u64 largesize = 0;
       
  2801     mp4_u32 type = 0;
       
  2802     mp4_i32 bytesread = 0;
       
  2803     mp4_i32 totalbytesread = 0;
       
  2804     MP4Err retError = MP4_OK;
       
  2805     userDataAtom* udta = NULL;
       
  2806     mp4_bool found = MP4FALSE;
       
  2807     mp4_u32 foundIndex = 0;
       
  2808 
       
  2809     MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  2810     
       
  2811     if (!handle)
       
  2812     	{
       
  2813         return MP4_ERROR;
       
  2814     	}
       
  2815     
       
  2816     if (!handle->metaDataComplete)
       
  2817         {
       
  2818         switch (metaDataAvailable(handle))
       
  2819             {
       
  2820             case 0:
       
  2821                 return MP4_NOT_AVAILABLE;
       
  2822             case 1:
       
  2823                 handle->cafError = KErrNone;
       
  2824                 if (readMetaData(handle) < 0)
       
  2825                     {
       
  2826 			      	// Reading of meta data failed, so free up any allocated memory
       
  2827 			  		freeFTYP(handle->ftyp);
       
  2828 			  		handle->ftyp = NULL;
       
  2829 					freeMOOV(handle->moov);
       
  2830 					handle->moov = NULL;
       
  2831                     
       
  2832                     if ( handle->cafError != KErrNone )
       
  2833                         {// if CAF/DRM caused the error return it instead of generic errorcode.
       
  2834                         return handle->cafError;
       
  2835                         }
       
  2836                     else
       
  2837                         {
       
  2838                         return MP4_INVALID_INPUT_STREAM;
       
  2839                         }
       
  2840                     }
       
  2841                 handle->metaDataComplete = MP4TRUE;
       
  2842                 break;
       
  2843 
       
  2844             case -2:
       
  2845               // Reading of FTYP meta data failed, so free up any allocated memory
       
  2846               freeFTYP(handle->ftyp);
       
  2847               handle->ftyp = NULL;
       
  2848               return MP4_ERROR;      
       
  2849 
       
  2850             case -1:
       
  2851             default:
       
  2852                 return MP4_ERROR;
       
  2853             }
       
  2854         }    
       
  2855 
       
  2856     if (!handle->moov)
       
  2857         return MP4_ERROR;
       
  2858 
       
  2859     // Check where to read udta from.
       
  2860     switch ( udtaLocation )
       
  2861         {
       
  2862         case MP4_UDTA_NONE:
       
  2863             {
       
  2864             retError = MP4_UDTA_NOT_FOUND;
       
  2865 			break;
       
  2866             }
       
  2867         case MP4_UDTA_MOOV:
       
  2868             {
       
  2869             if ( !handle->moov->udta )
       
  2870                 {
       
  2871                 retError = MP4_UDTA_NOT_FOUND;
       
  2872                 break;
       
  2873                 }
       
  2874             else
       
  2875                 {
       
  2876                 udta = handle->moov->udta;
       
  2877                 }
       
  2878             break;
       
  2879             }
       
  2880         case MP4_UDTA_VIDEOTRAK:
       
  2881             {
       
  2882             if ( !handle->moov->trakVideo )
       
  2883                 {
       
  2884                 retError = MP4_UDTA_NOT_FOUND;
       
  2885                 break;
       
  2886                 }
       
  2887             if ( !handle->moov->trakVideo->udta )
       
  2888                 {
       
  2889                 retError = MP4_UDTA_NOT_FOUND;
       
  2890                 }
       
  2891             else
       
  2892                 {
       
  2893                 udta = handle->moov->trakVideo->udta;
       
  2894                 }
       
  2895             break;
       
  2896             }
       
  2897         case MP4_UDTA_AUDIOTRAK:
       
  2898             {
       
  2899             if (!handle->moov->trakAudio)
       
  2900                 {
       
  2901                 retError = MP4_UDTA_NOT_FOUND;
       
  2902                 break;
       
  2903                 }
       
  2904             if ( !handle->moov->trakAudio->udta )
       
  2905                 {
       
  2906                 retError = MP4_UDTA_NOT_FOUND;
       
  2907                 }
       
  2908             else
       
  2909                 {
       
  2910                 udta = handle->moov->trakAudio->udta;
       
  2911                 }
       
  2912             break;
       
  2913             }
       
  2914        default:
       
  2915             {
       
  2916             retError = MP4_INVALID_TYPE;
       
  2917             }
       
  2918         }
       
  2919 
       
  2920     if ( retError == MP4_OK )   // valid UDTA found.
       
  2921         {
       
  2922         if ( !udta->atomhdr )
       
  2923             {
       
  2924             retError = MP4_UDTA_NOT_FOUND;
       
  2925             }
       
  2926         if ( !udta->atomcontentloc || (udta->atomcontentsize == 0) )
       
  2927             {
       
  2928             retError = MP4_UDTA_NOT_FOUND;
       
  2929             }
       
  2930 
       
  2931         // seek to UDTA atom in memory structure or file.
       
  2932         if (handle->file) /* Input is in a file */
       
  2933             {
       
  2934             if (seekFileAbs(handle, udta->atomcontentloc) != 0)
       
  2935                 return MP4_CANT_SEEK;
       
  2936             }
       
  2937         else
       
  2938             {
       
  2939             handle->absPosition = udta->atomcontentloc;
       
  2940             }
       
  2941         
       
  2942         // search for wanted atom from UDTA and read it to buffer
       
  2943         while ( totalbytesread < (mp4_i32)udta->atomcontentsize )
       
  2944             {
       
  2945             if (peekData(handle, handle->buf, 16) < 0)
       
  2946                 return MP4_ERROR;
       
  2947 
       
  2948             size = u32endian(*((mp4_u32 *)handle->buf));
       
  2949             type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  2950         
       
  2951             if ( type == udtaAtomType )
       
  2952                 {
       
  2953                 if ( atomIndex == foundIndex )
       
  2954                     {
       
  2955                     if ( size == 1 )
       
  2956                         {
       
  2957                         largesize = u64endian(*((mp4_u64*)(handle->buf+8)));
       
  2958                         size = (mp4_u32)I64INT(largesize);
       
  2959                         }
       
  2960                     if ( size > bufferSize )
       
  2961                         {
       
  2962                         // Although the output buffer supplied by the caller is 
       
  2963                         // not large enough to store the sub user atom's content, keep 
       
  2964                         // parsing thru the whole user data to retrieve the highest index
       
  2965                         // to be returned thru the atomIndex parameter
       
  2966                         bufferSize = size;
       
  2967                         retError = MP4_OUTPUT_BUFFER_TOO_SMALL;
       
  2968                         bytesread = readUnknown(handle);
       
  2969 	                	if (bytesread < 0)
       
  2970 	                		return MP4_ERROR;
       
  2971 						}
       
  2972                     else
       
  2973                     	{
       
  2974 	                    bytesread = readData(handle, buffer, size);
       
  2975 	                    if (bytesread < 0)
       
  2976 	                        return MP4_ERROR;
       
  2977 	                    bufferSize = bytesread;                    		
       
  2978                     	}
       
  2979                     	
       
  2980                     totalbytesread += bytesread;
       
  2981                     foundIndex += 1;
       
  2982                     found = MP4TRUE;
       
  2983                     }
       
  2984                 else
       
  2985                     {
       
  2986                 	bytesread = readUnknown(handle);
       
  2987                 	if (bytesread < 0)
       
  2988                 		return MP4_ERROR;
       
  2989                 	totalbytesread += bytesread;
       
  2990                 	foundIndex += 1;
       
  2991                     }
       
  2992                 }
       
  2993             else
       
  2994                 {
       
  2995                 bytesread = readUnknown(handle);
       
  2996                 if (bytesread < 0)
       
  2997                     return MP4_ERROR;
       
  2998                 totalbytesread += bytesread;
       
  2999                 }
       
  3000             }
       
  3001         }
       
  3002 
       
  3003     if ( ( atomIndex > foundIndex ) || !found )
       
  3004         {
       
  3005         retError = MP4_UDTA_NOT_FOUND;
       
  3006         }
       
  3007 
       
  3008     // fill how many wanted type atom there is in asked UDTA.
       
  3009     if ( found )
       
  3010         {
       
  3011         atomIndex = foundIndex - 1;
       
  3012         }
       
  3013     else
       
  3014         {
       
  3015         atomIndex = 0;
       
  3016         }
       
  3017 
       
  3018     // fill udtaLocation
       
  3019     udtaLocation = MP4_UDTA_NONE;
       
  3020 
       
  3021     if ( handle->moov->udta )
       
  3022         {
       
  3023         udtaLocation |= MP4_UDTA_MOOV;
       
  3024         }
       
  3025     if ( handle->moov->trakVideo )
       
  3026         {
       
  3027         if ( handle->moov->trakVideo->udta )
       
  3028             {
       
  3029             udtaLocation |= MP4_UDTA_VIDEOTRAK;
       
  3030             }
       
  3031         }
       
  3032     if ( handle->moov->trakAudio )
       
  3033         {
       
  3034         if ( handle->moov->trakAudio->udta )
       
  3035             {
       
  3036             udtaLocation |= MP4_UDTA_AUDIOTRAK;
       
  3037             }
       
  3038         }
       
  3039 
       
  3040     return retError;
       
  3041     }
       
  3042 
       
  3043 extern EXPORT_C MP4Err MP4ParseNextVideoFrameDependencies(MP4Handle apihandle, mp4_u8* aDependsOn, mp4_u8* aIsDependentOn, mp4_u8* aHasRedundancy)
       
  3044 {
       
  3045 	MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  3046 	mp4_u32 type = 0;
       
  3047 	
       
  3048 	if (!handle)
       
  3049 	    {
       
  3050 		return MP4_ERROR;
       
  3051 	    }
       
  3052 	if(!aDependsOn || !aIsDependentOn || !aHasRedundancy)
       
  3053 	    {
       
  3054 		return MP4_NO_OUTPUT_BUFFER;
       
  3055 	    }
       
  3056 	if (!handle->metaDataComplete)
       
  3057 	{
       
  3058 		switch (metaDataAvailable(handle))
       
  3059 		{
       
  3060 		case 0:
       
  3061 			return MP4_NOT_AVAILABLE;
       
  3062 
       
  3063 		case 1:
       
  3064 			if (readMetaData(handle) < 0)
       
  3065 				{
       
  3066 		      	// Reading of meta data failed, so free up any allocated memory
       
  3067 		  		freeFTYP(handle->ftyp);
       
  3068 		  		handle->ftyp = NULL;
       
  3069 				freeMOOV(handle->moov);
       
  3070 				handle->moov = NULL;
       
  3071 				
       
  3072 				return MP4_INVALID_INPUT_STREAM;
       
  3073 				}
       
  3074 
       
  3075 			handle->metaDataComplete = MP4TRUE;
       
  3076 			break;
       
  3077 
       
  3078 	    case -2:
       
  3079 	      // Reading of FTYP meta data failed, so free up any allocated memory
       
  3080 	      freeFTYP(handle->ftyp);
       
  3081 	      handle->ftyp = NULL;
       
  3082 	      return MP4_ERROR;      
       
  3083 
       
  3084 		case -1:
       
  3085 		default:
       
  3086 			return MP4_ERROR;
       
  3087 		}
       
  3088 	}
       
  3089     
       
  3090     if (determineVideoType(handle, &type) < 0)
       
  3091         {
       
  3092         return MP4_ERROR;
       
  3093         }
       
  3094     if( !isAvcVideo(type) )
       
  3095         {
       
  3096         *aDependsOn = 0; // Unknown
       
  3097         *aIsDependentOn = 0; // Unknown
       
  3098         *aHasRedundancy = 0; // Unknown
       
  3099         return MP4_OK;
       
  3100         }	
       
  3101 
       
  3102     if (!handle->moov)
       
  3103         return MP4_ERROR;
       
  3104     if (!handle->moov->trakVideo)
       
  3105         return MP4_ERROR;
       
  3106     if (!handle->moov->trakVideo->mdia)
       
  3107         return MP4_ERROR;
       
  3108     if (!handle->moov->trakVideo->mdia->minf)
       
  3109         return MP4_ERROR;
       
  3110     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  3111         return MP4_ERROR;
       
  3112     if (!handle->moov->trakVideo->mdia->minf->stbl->sdtp)
       
  3113         {
       
  3114         *aDependsOn = 0; // Unknown
       
  3115         *aIsDependentOn = 0; // Unknown
       
  3116         *aHasRedundancy = 0; // Unknown
       
  3117         return MP4_OK;
       
  3118         }
       
  3119     if (!handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep)
       
  3120         {
       
  3121         return MP4_ERROR;
       
  3122         }
       
  3123         
       
  3124     if (handle->videoSampleNum <= 0)    
       
  3125     	{
       
  3126     	return MP4_ERROR;	
       
  3127     	}
       
  3128         
       
  3129     if(handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sDependsOn > 2 ||
       
  3130        handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sIsDependentOn > 2 ||
       
  3131        handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sHasRedundancy > 2)
       
  3132         {
       
  3133     	return MP4_ERROR;
       
  3134         }
       
  3135     *aDependsOn = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sDependsOn;
       
  3136     *aIsDependentOn = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sIsDependentOn;
       
  3137     *aHasRedundancy = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sHasRedundancy;
       
  3138     return MP4_OK;
       
  3139 }
       
  3140 
       
  3141 extern EXPORT_C MP4Err MP4ParseReadAudioFramesAsync(MP4Handle apihandle, M3GPMP4LibAsyncObserver* aObserver, mp4_u8 *buffer, mp4_u32* buffersize)
       
  3142 {
       
  3143   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  3144   
       
  3145 	if (!handle->file)
       
  3146 		{
       
  3147 		// async operation is only supported for files.
       
  3148 		return MP4_FILE_ERROR;
       
  3149 		}	
       
  3150 
       
  3151   if (!handle->metaDataComplete)
       
  3152   {
       
  3153     switch (metaDataAvailable(handle))
       
  3154     {
       
  3155     case 0:
       
  3156       return MP4_NOT_AVAILABLE;
       
  3157     case 1:
       
  3158       handle->cafError = KErrNone;
       
  3159       if (readMetaData(handle) < 0)
       
  3160       {
       
  3161       	// Reading of meta data failed, so free up any allocated memory
       
  3162   		freeFTYP(handle->ftyp);
       
  3163   		handle->ftyp = NULL;
       
  3164 		freeMOOV(handle->moov);
       
  3165 		handle->moov = NULL;
       
  3166       
       
  3167       	if ( handle->cafError != KErrNone )
       
  3168       	{
       
  3169       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
  3170       	  return handle->cafError;
       
  3171       	}
       
  3172       	else
       
  3173       	{
       
  3174 	      return MP4_INVALID_INPUT_STREAM;
       
  3175       	}
       
  3176       }
       
  3177       handle->metaDataComplete = MP4TRUE;
       
  3178       break;
       
  3179 
       
  3180     case -2:
       
  3181       // Reading of FTYP meta data failed, so free up any allocated memory
       
  3182       freeFTYP(handle->ftyp);
       
  3183       handle->ftyp = NULL;
       
  3184       return MP4_ERROR;      
       
  3185 
       
  3186     case -1:
       
  3187     default:
       
  3188       return MP4_ERROR;
       
  3189     }
       
  3190   }
       
  3191   
       
  3192   handle->asyncObserver = aObserver;
       
  3193 
       
  3194   /* Is audio available? */
       
  3195   if (!((handle->type & MP4_TYPE_MPEG4_AUDIO) ||
       
  3196         (handle->type & MP4_TYPE_AMR_NB) ||
       
  3197         (handle->type & MP4_TYPE_AMR_WB) ||
       
  3198         (handle->type & MP4_TYPE_QCELP_13K)))
       
  3199     return MP4_ERROR;
       
  3200 
       
  3201   /* Are there samples left? */
       
  3202   if (handle->audioLast)
       
  3203     return MP4_NO_FRAME;
       
  3204 
       
  3205   if (!handle->moov)
       
  3206     return MP4_ERROR;
       
  3207   if (!handle->moov->trakAudio)
       
  3208     return MP4_ERROR;
       
  3209   
       
  3210   switch (fetchAudioSampleAsync(handle, handle->moov->trakAudio, buffer, buffersize))
       
  3211   {
       
  3212   case -1:
       
  3213     return MP4_ERROR;
       
  3214   case -2:
       
  3215     return MP4_BUFFER_TOO_SMALL;
       
  3216   case -4:
       
  3217     return MP4_INVALID_INPUT_STREAM;
       
  3218   case MP4_OUT_OF_MEMORY:
       
  3219     return MP4_OUT_OF_MEMORY;
       
  3220   default:
       
  3221     break;
       
  3222   }  
       
  3223   return MP4_OK;
       
  3224 }
       
  3225 
       
  3226 extern EXPORT_C MP4Err MP4ParseReadVideoFrameAsync(MP4Handle apihandle,
       
  3227  																M3GPMP4LibAsyncObserver* aObserver, 		
       
  3228                             							       	mp4_u8* buffer,
       
  3229                                    								mp4_u32* buffersize)
       
  3230 {
       
  3231   MP4HandleImp handle = (MP4HandleImp)apihandle;
       
  3232   
       
  3233 	if (!handle->file)
       
  3234 		{
       
  3235 		// async operation is only supported for files.
       
  3236 		return MP4_FILE_ERROR;
       
  3237 		}
       
  3238 
       
  3239   if (!handle->metaDataComplete)
       
  3240   {
       
  3241     switch (metaDataAvailable(handle))
       
  3242     {
       
  3243     case 0:
       
  3244 
       
  3245       return MP4_NOT_AVAILABLE;
       
  3246 
       
  3247     case 1:
       
  3248       handle->cafError = KErrNone;
       
  3249       if (readMetaData(handle) < 0)
       
  3250       {
       
  3251       	// Reading of meta data failed, so free up any allocated memory
       
  3252   		freeFTYP(handle->ftyp);
       
  3253   		handle->ftyp = NULL;
       
  3254 		freeMOOV(handle->moov);
       
  3255 		handle->moov = NULL;
       
  3256       
       
  3257       	if ( handle->cafError != KErrNone )
       
  3258       	{
       
  3259       	  // if CAF/DRM caused the error return it instead of generic errorcode.
       
  3260       	  return handle->cafError;
       
  3261       	}
       
  3262       	else
       
  3263       	{
       
  3264 	      return MP4_INVALID_INPUT_STREAM;
       
  3265       	}
       
  3266       }
       
  3267       handle->metaDataComplete = MP4TRUE;
       
  3268       break;
       
  3269 
       
  3270     case -2:
       
  3271       // Reading of FTYP meta data failed, so free up any allocated memory
       
  3272       freeFTYP(handle->ftyp);
       
  3273       handle->ftyp = NULL;
       
  3274       return MP4_ERROR;      
       
  3275 
       
  3276     case -1:
       
  3277     default:
       
  3278       return MP4_ERROR;
       
  3279     }
       
  3280   }
       
  3281 
       
  3282   /* Is video available? */
       
  3283   if (!((handle->type & MP4_TYPE_MPEG4_VIDEO) ||
       
  3284         (handle->type & MP4_TYPE_H263_PROFILE_0) ||
       
  3285         (handle->type & MP4_TYPE_H263_PROFILE_3) ||
       
  3286 		containsAvcVideo( handle->type ) ))
       
  3287     return MP4_ERROR;
       
  3288 
       
  3289   /* Are there samples left? */
       
  3290   if (handle->videoLast)
       
  3291     return MP4_NO_FRAME;
       
  3292   
       
  3293   handle->asyncObserver = aObserver;  
       
  3294 
       
  3295   if (!handle->moov)
       
  3296     return MP4_ERROR;
       
  3297   if (!handle->moov->trakVideo)
       
  3298     return MP4_ERROR;
       
  3299 
       
  3300   switch (fetchVideoFrameAsync(handle, handle->moov->trakVideo, buffer, buffersize ))
       
  3301   {
       
  3302   case -1:
       
  3303     return MP4_ERROR;
       
  3304   case -2:
       
  3305     return MP4_BUFFER_TOO_SMALL;
       
  3306   case -3:
       
  3307     return MP4_NOT_AVAILABLE;
       
  3308   case -4:
       
  3309     return MP4_INVALID_INPUT_STREAM;
       
  3310   case MP4_OUT_OF_MEMORY:
       
  3311     return MP4_OUT_OF_MEMORY;
       
  3312   default:
       
  3313     break;
       
  3314   }
       
  3315 
       
  3316   return MP4_OK;
       
  3317 }
       
  3318 
       
  3319 extern EXPORT_C void MP4CancelReadFrame(MP4Handle ahandle)
       
  3320 	{
       
  3321 	MP4HandleImp handle = (MP4HandleImp)ahandle;
       
  3322 	
       
  3323 	if (handle->asyncReader)
       
  3324 		{
       
  3325 		handle->asyncReader->Cancel();
       
  3326 		}
       
  3327 	}
       
  3328 
       
  3329 // End of File