os/mm/mmplugins/lib3gp/impl/src/mp4parse.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 extern EXPORT_C MP4Err MP4ParseGetID32Location(MP4Handle apihandle, mp4_u32& location)
  3330     { 
  3331     MP4HandleImp handle = (MP4HandleImp)apihandle;
  3332 
  3333     if (!handle)
  3334         {
  3335         return MP4_ERROR;
  3336         }
  3337 
  3338     if (!handle->metaDataComplete)
  3339         {
  3340         switch (metaDataAvailable(handle))
  3341             {
  3342             case 0:
  3343                 return MP4_NOT_AVAILABLE;
  3344             case 1:
  3345                 handle->cafError = KErrNone;
  3346                 if (readMetaData(handle) < 0)
  3347                     {
  3348 			      	// Reading of meta data failed, so free up any allocated memory
  3349 			  		freeFTYP(handle->ftyp);
  3350 			  		handle->ftyp = NULL;
  3351 					freeMOOV(handle->moov);
  3352 					handle->moov = NULL;
  3353                     if (handle->cafError != KErrNone)
  3354                         {// if CAF/DRM caused the error return it instead of generic errorcode.
  3355                         return handle->cafError;
  3356                         }
  3357                     else
  3358                         {
  3359                         return MP4_INVALID_INPUT_STREAM;
  3360                         }
  3361                     }
  3362                 handle->metaDataComplete = MP4TRUE;
  3363                 break;
  3364 
  3365 		    case -2:
  3366                 // Reading of FTYP meta data failed, so free up any allocated memory
  3367                 freeFTYP(handle->ftyp);
  3368                 handle->ftyp = NULL;
  3369                 return MP4_ERROR;
  3370 		      
  3371             case -1:
  3372             default:
  3373                 return MP4_ERROR;
  3374             }
  3375         }    
  3376 
  3377     if (!handle->moov)
  3378         return MP4_ERROR;
  3379 
  3380     metaAtom* meta = handle->moov->meta;
  3381     if (!meta)
  3382         return MP4_NOT_AVAILABLE;
  3383 
  3384     if (!meta->atomhdr)
  3385         return MP4_NOT_AVAILABLE;
  3386     
  3387     if(meta->ID32)
  3388         {
  3389         location = meta->ID32->atomcontentloc;     
  3390         }
  3391     else
  3392         {
  3393         return MP4_NOT_AVAILABLE;
  3394         }    
  3395 
  3396     return MP4_OK;
  3397     }
  3398 // End of File