1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmplugins/lib3gp/impl/src/mp4parse.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3398 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <3gplibrary/mp4config.h>
1.20 +#include <3gplibrary/mp4lib.h>
1.21 +#include "mp4atom.h"
1.22 +#include "mp4memwrap.h"
1.23 +#include "mp4file.h"
1.24 +#include "mp4buffer.h"
1.25 +#include "mp4endian.h"
1.26 +#include "mp4utils.h"
1.27 +
1.28 +using namespace ContentAccess;
1.29 +
1.30 +extern EXPORT_C MP4Err MP4ParseOpen(MP4Handle *apihandle,
1.31 + MP4FileName filename)
1.32 +{
1.33 + MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
1.34 + *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
1.35 + if (*handle == NULL)
1.36 + return MP4_OUT_OF_MEMORY;
1.37 +
1.38 + (*handle)->file32Duplicate = NULL;
1.39 + (*handle)->FileHandleFromOutside = EFalse;
1.40 + (*handle)->sourceType = MP4_SOURCE_RFILE;
1.41 +
1.42 + if (filename)
1.43 + if (initFileRead(filename, *handle) == -1)
1.44 + {
1.45 + closeFile(*handle);
1.46 + mp4free(*handle);
1.47 + *handle = NULL;
1.48 + return MP4_FILE_ERROR;
1.49 + }
1.50 +
1.51 + (*handle)->mem = listCreate();
1.52 + if ((*handle)->mem == NULL)
1.53 + {
1.54 + closeFile(*handle);
1.55 + mp4free(*handle);
1.56 + *handle = NULL;
1.57 + return MP4_OUT_OF_MEMORY;
1.58 + }
1.59 +
1.60 + if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
1.61 + {
1.62 + listDestroyList((*handle)->mem);
1.63 + closeFile(*handle);
1.64 + mp4free(*handle);
1.65 + *handle = NULL;
1.66 + return MP4_OUT_OF_MEMORY;
1.67 + }
1.68 +
1.69 + if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
1.70 + {
1.71 + mp4free((*handle)->buf);
1.72 + listDestroyList((*handle)->mem);
1.73 + closeFile(*handle);
1.74 + mp4free(*handle);
1.75 + *handle = NULL;
1.76 + return MP4_OUT_OF_MEMORY;
1.77 + }
1.78 +
1.79 + // register for stblib use
1.80 + if (openStdlib() != MP4_OK)
1.81 + {
1.82 + mp4free((*handle)->diskReadBuf);
1.83 + mp4free((*handle)->buf);
1.84 + listDestroyList((*handle)->mem);
1.85 + closeFile(*handle);
1.86 + mp4free(*handle);
1.87 + *handle = NULL;
1.88 +
1.89 + return MP4_ERROR;
1.90 + }
1.91 +
1.92 + return MP4_OK;
1.93 +}
1.94 +
1.95 +extern EXPORT_C MP4Err MP4ParseOpenFileHandle(MP4Handle *apihandle,
1.96 + RFile *inputfile)
1.97 +{
1.98 + MP4Err err;
1.99 + RFile64 *f64 = new RFile64;
1.100 + if (f64 == NULL)
1.101 + {
1.102 + return MP4_OUT_OF_MEMORY;
1.103 + }
1.104 + if (f64->Duplicate(*inputfile) != KErrNone)
1.105 + {
1.106 + delete f64;
1.107 + return MP4_ERROR;
1.108 + }
1.109 + err = MP4ParseOpenFileHandle64(apihandle, f64);
1.110 + if (err == MP4_OK)
1.111 + {
1.112 + MP4HandleImp* handle = (MP4HandleStruct **)apihandle;
1.113 + (*handle)->file32Duplicate = (void*)(f64);
1.114 + }
1.115 + return err;
1.116 +}
1.117 +
1.118 +extern EXPORT_C MP4Err MP4ParseOpenFileHandle64(MP4Handle *apihandle,
1.119 + RFile64 *inputfile)
1.120 +{
1.121 + MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
1.122 + *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
1.123 + if (*handle == NULL)
1.124 + return MP4_OUT_OF_MEMORY;
1.125 +
1.126 + (*handle)->file32Duplicate = NULL;
1.127 + (*handle)->rfile = (void *)inputfile;
1.128 + (*handle)->file = (*handle)->rfile;
1.129 + (*handle)->FileHandleFromOutside = ETrue;
1.130 + (*handle)->sourceType = MP4_SOURCE_RFILE;
1.131 + if (inputfile == NULL)
1.132 + {
1.133 + closeFile(*handle);
1.134 + mp4free(*handle);
1.135 + *handle = NULL;
1.136 + return MP4_FILE_ERROR;
1.137 + }
1.138 +
1.139 + (*handle)->mem = listCreate();
1.140 + if ((*handle)->mem == NULL)
1.141 + {
1.142 + closeFile(*handle);
1.143 + mp4free(*handle);
1.144 + *handle = NULL;
1.145 + return MP4_OUT_OF_MEMORY;
1.146 + }
1.147 +
1.148 + if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
1.149 + {
1.150 + listDestroyList((*handle)->mem);
1.151 + closeFile(*handle);
1.152 + mp4free(*handle);
1.153 + *handle = NULL;
1.154 + return MP4_OUT_OF_MEMORY;
1.155 + }
1.156 +
1.157 + if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
1.158 + {
1.159 + mp4free((*handle)->buf);
1.160 + listDestroyList((*handle)->mem);
1.161 + closeFile(*handle);
1.162 + mp4free(*handle);
1.163 + *handle = NULL;
1.164 + return MP4_OUT_OF_MEMORY;
1.165 + }
1.166 +
1.167 + // register for stblib use
1.168 + if (openStdlib() != MP4_OK)
1.169 + {
1.170 + // clean up
1.171 + mp4free((*handle)->diskReadBuf);
1.172 + mp4free((*handle)->buf);
1.173 + listDestroyList((*handle)->mem);
1.174 + closeFile(*handle);
1.175 + mp4free(*handle);
1.176 + *handle = NULL;
1.177 +
1.178 + return MP4_ERROR;
1.179 + }
1.180 +
1.181 + return MP4_OK;
1.182 +}
1.183 +
1.184 +extern EXPORT_C MP4Err MP4ParseOpenCAF(MP4Handle *apihandle,
1.185 + ContentAccess::CData *inputfile)
1.186 +{
1.187 + MP4HandleImp *handle = (MP4HandleStruct **)apihandle;
1.188 + *handle = (MP4HandleImp)mp4malloc(sizeof(MP4HandleStruct));
1.189 + if (*handle == NULL)
1.190 + return MP4_OUT_OF_MEMORY;
1.191 +
1.192 + (*handle)->file32Duplicate = NULL;
1.193 + (*handle)->cfile = inputfile;
1.194 + (*handle)->file = (*handle)->cfile;
1.195 + (*handle)->FileHandleFromOutside = ETrue;
1.196 + (*handle)->sourceType = MP4_SOURCE_CAF;
1.197 +
1.198 + if (inputfile == NULL)
1.199 + {
1.200 + closeFile(*handle);
1.201 + mp4free(*handle);
1.202 + *handle = NULL;
1.203 + return MP4_FILE_ERROR;
1.204 + }
1.205 +
1.206 + (*handle)->mem = listCreate();
1.207 + if ((*handle)->mem == NULL)
1.208 + {
1.209 + closeFile(*handle);
1.210 + mp4free(*handle);
1.211 + *handle = NULL;
1.212 + return MP4_OUT_OF_MEMORY;
1.213 + }
1.214 +
1.215 + if (((*handle)->buf = (mp4_u8 *)mp4malloc(TMPBUFSIZE)) == NULL)
1.216 + {
1.217 + listDestroyList((*handle)->mem);
1.218 + closeFile(*handle);
1.219 + mp4free(*handle);
1.220 + *handle = NULL;
1.221 + return MP4_OUT_OF_MEMORY;
1.222 + }
1.223 +
1.224 + if (((*handle)->diskReadBuf = (mp4_u8 *)mp4malloc(READBUFSIZE)) == NULL)
1.225 + {
1.226 + mp4free((*handle)->buf);
1.227 + listDestroyList((*handle)->mem);
1.228 + closeFile(*handle);
1.229 + mp4free(*handle);
1.230 + *handle = NULL;
1.231 + return MP4_OUT_OF_MEMORY;
1.232 + }
1.233 +
1.234 + // register for stblib use
1.235 + if (openStdlib() != MP4_OK)
1.236 + {
1.237 + // clean up
1.238 + mp4free((*handle)->diskReadBuf);
1.239 + mp4free((*handle)->buf);
1.240 + listDestroyList((*handle)->mem);
1.241 + closeFile(*handle);
1.242 + mp4free(*handle);
1.243 + *handle = NULL;
1.244 +
1.245 + return MP4_ERROR;
1.246 + }
1.247 +
1.248 + return MP4_OK;
1.249 +}
1.250 +
1.251 +extern EXPORT_C MP4Err MP4ParseClose(MP4Handle apihandle)
1.252 +{
1.253 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.254 +
1.255 + if (!handle)
1.256 + return MP4_ERROR;
1.257 +
1.258 + if (handle->file)
1.259 + closeFile(handle);
1.260 +
1.261 + closeStdlib(); /* Free memory allocated by stdlib wrapper functions */
1.262 +
1.263 + listDestroyList(handle->mem);
1.264 +
1.265 + if (handle->diskReadBuf)
1.266 + mp4free(handle->diskReadBuf);
1.267 +
1.268 + if (handle->buf)
1.269 + mp4free(handle->buf);
1.270 +
1.271 + if (freeMOOV(handle->moov) < 0)
1.272 + return MP4_ERROR;
1.273 +
1.274 + if (freeFTYP(handle->ftyp) < 0)
1.275 + return MP4_ERROR;
1.276 +
1.277 + if (handle->file32Duplicate)
1.278 + ((RFile64*)handle->file32Duplicate)->Close();
1.279 +
1.280 + if (handle)
1.281 + mp4free(handle);
1.282 +
1.283 + return MP4_OK;
1.284 +}
1.285 +
1.286 +extern EXPORT_C MP4Err MP4ParseRequestVideoDescription(MP4Handle apihandle,
1.287 + mp4_u32 *videolength,
1.288 + mp4_double *framerate,
1.289 + mp4_u32 *videotype,
1.290 + mp4_u32 *videowidth,
1.291 + mp4_u32 *videoheight,
1.292 + mp4_u32 *timescale)
1.293 +{
1.294 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.295 + if (!handle)
1.296 + {
1.297 + return MP4_ERROR;
1.298 + }
1.299 +
1.300 + if (!handle->metaDataComplete)
1.301 + {
1.302 + switch (metaDataAvailable(handle))
1.303 + {
1.304 + case 0:
1.305 + return MP4_NOT_AVAILABLE;
1.306 +
1.307 + case 1:
1.308 + handle->cafError = KErrNone;
1.309 + if (readMetaData(handle) < 0)
1.310 + {
1.311 + // Reading of meta data failed, so free up any allocated memory
1.312 + freeFTYP(handle->ftyp);
1.313 + handle->ftyp = NULL;
1.314 + freeMOOV(handle->moov);
1.315 + handle->moov = NULL;
1.316 +
1.317 + if ( handle->cafError != KErrNone )
1.318 + {
1.319 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.320 + return handle->cafError;
1.321 + }
1.322 + else
1.323 + {
1.324 + return MP4_INVALID_INPUT_STREAM;
1.325 + }
1.326 + }
1.327 + handle->metaDataComplete = MP4TRUE;
1.328 + break;
1.329 +
1.330 + case -2:
1.331 + // Reading of FTYP meta data failed, so free up any allocated memory
1.332 + freeFTYP(handle->ftyp);
1.333 + handle->ftyp = NULL;
1.334 + return MP4_ERROR;
1.335 +
1.336 + case -1:
1.337 + default:
1.338 + return MP4_ERROR;
1.339 + }
1.340 + }
1.341 +
1.342 + if (!handle->moov)
1.343 + return MP4_ERROR;
1.344 + if (!handle->moov->trakVideo)
1.345 + return MP4_NO_VIDEO;
1.346 +
1.347 + mp4_i32 videoError = 0;
1.348 + videoError = determineVideoType(handle, videotype);
1.349 + if ( videoError == -2 )
1.350 + {
1.351 + return MP4_NO_VIDEO;
1.352 + }
1.353 + else if ( videoError < 0 )
1.354 + {
1.355 + return MP4_ERROR;
1.356 + }
1.357 +
1.358 + if (determineVideoLength(handle, videolength) < 0)
1.359 + return MP4_ERROR;
1.360 +
1.361 + if (determineFrameRate(handle, framerate) < 0)
1.362 + return MP4_ERROR;
1.363 +
1.364 + if (determineVideoResolution(handle, videowidth, videoheight) < 0)
1.365 + return MP4_ERROR;
1.366 +
1.367 + if (determineVideoTimeScale(handle, timescale) < 0)
1.368 + return MP4_ERROR;
1.369 +
1.370 +
1.371 + return MP4_OK;
1.372 +}
1.373 +
1.374 +extern EXPORT_C MP4Err MP4ParseRequestAudioDescription(MP4Handle apihandle,
1.375 + mp4_u32 *audiolength,
1.376 + mp4_u32 *audiotype,
1.377 + mp4_u8 *framespersample,
1.378 + mp4_u32 *timescale,
1.379 + mp4_u32 *averagebitrate)
1.380 +{
1.381 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.382 + if (!handle)
1.383 + {
1.384 + return MP4_ERROR;
1.385 + }
1.386 +
1.387 + if (!handle->metaDataComplete)
1.388 + {
1.389 + switch (metaDataAvailable(handle))
1.390 + {
1.391 + case 0:
1.392 + return MP4_NOT_AVAILABLE;
1.393 +
1.394 + case 1:
1.395 + handle->cafError = KErrNone;
1.396 + if (readMetaData(handle) < 0)
1.397 + {
1.398 + // Reading of meta data failed, so free up any allocated memory
1.399 + freeFTYP(handle->ftyp);
1.400 + handle->ftyp = NULL;
1.401 + freeMOOV(handle->moov);
1.402 + handle->moov = NULL;
1.403 +
1.404 + if ( handle->cafError != KErrNone )
1.405 + {
1.406 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.407 + return handle->cafError;
1.408 + }
1.409 + else
1.410 + {
1.411 + return MP4_INVALID_INPUT_STREAM;
1.412 + }
1.413 + }
1.414 +
1.415 + handle->metaDataComplete = MP4TRUE;
1.416 + break;
1.417 +
1.418 + case -2:
1.419 + // Reading of FTYP meta data failed, so free up any allocated memory
1.420 + freeFTYP(handle->ftyp);
1.421 + handle->ftyp = NULL;
1.422 + return MP4_ERROR;
1.423 +
1.424 + case -1:
1.425 + default:
1.426 + return MP4_ERROR;
1.427 + }
1.428 + }
1.429 +
1.430 + if (!handle->moov)
1.431 + return MP4_ERROR;
1.432 + if (!handle->moov->trakAudio)
1.433 + return MP4_NO_AUDIO;
1.434 +
1.435 + if (determineAudioLength(handle, audiolength) < 0)
1.436 + return MP4_ERROR;
1.437 +
1.438 + mp4_i32 audioError = 0;
1.439 + audioError = determineAudioType(handle, audiotype);
1.440 + if ( audioError == -2 )
1.441 + {
1.442 + return MP4_NO_AUDIO;
1.443 + }
1.444 + else if ( audioError < 0 )
1.445 + {
1.446 + return MP4_ERROR;
1.447 + }
1.448 +
1.449 + if (determineAudioFramesPerSample(handle, framespersample) < 0)
1.450 + return MP4_ERROR;
1.451 +
1.452 + if (determineAudioTimeScale(handle, timescale) < 0)
1.453 + return MP4_ERROR;
1.454 +
1.455 + if (averagebitrate != NULL)
1.456 + if (determineAudioAverageBitRate(handle, averagebitrate) < 0)
1.457 + return MP4_ERROR;
1.458 +
1.459 +
1.460 + return MP4_OK;
1.461 +}
1.462 +
1.463 +extern EXPORT_C MP4Err MP4ParseRequestStreamDescription(MP4Handle apihandle,
1.464 + mp4_u32 *streamsize,
1.465 + mp4_u32 *streamaveragebitrate)
1.466 +{
1.467 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.468 +
1.469 + if (!handle->metaDataComplete)
1.470 + {
1.471 + switch (metaDataAvailable(handle))
1.472 + {
1.473 + case 0:
1.474 +
1.475 + return MP4_NOT_AVAILABLE;
1.476 +
1.477 + case 1:
1.478 + handle->cafError = KErrNone;
1.479 + if (readMetaData(handle) < 0)
1.480 + {
1.481 + // Reading of meta data failed, so free up any allocated memory
1.482 + freeFTYP(handle->ftyp);
1.483 + handle->ftyp = NULL;
1.484 + freeMOOV(handle->moov);
1.485 + handle->moov = NULL;
1.486 +
1.487 + if ( handle->cafError != KErrNone )
1.488 + {
1.489 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.490 + return handle->cafError;
1.491 + }
1.492 + else
1.493 + {
1.494 + return MP4_INVALID_INPUT_STREAM;
1.495 + }
1.496 + }
1.497 + handle->metaDataComplete = MP4TRUE;
1.498 + break;
1.499 +
1.500 + case -2:
1.501 + // Reading of FTYP meta data failed, so free up any allocated memory
1.502 + freeFTYP(handle->ftyp);
1.503 + handle->ftyp = NULL;
1.504 + return MP4_ERROR;
1.505 +
1.506 + case -1:
1.507 + default:
1.508 + return MP4_ERROR;
1.509 + }
1.510 + }
1.511 +
1.512 + if (determineStreamSize(handle, streamsize) < 0)
1.513 + return MP4_ERROR;
1.514 +
1.515 + if (determineStreamAverageBitRate(handle, streamaveragebitrate, *streamsize) < 0)
1.516 + return MP4_ERROR;
1.517 +
1.518 +
1.519 + return MP4_OK;
1.520 +}
1.521 +
1.522 +extern EXPORT_C MP4Err MP4ParseWriteData(MP4Handle apihandle,
1.523 + mp4_u8 *buffer,
1.524 + mp4_u32 bytestowrite)
1.525 +{
1.526 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.527 +
1.528 + if (handle->file)
1.529 + return MP4_ERROR;
1.530 +
1.531 + if ((buffer == NULL) && (bytestowrite != 0))
1.532 + return MP4_ERROR;
1.533 +
1.534 + if (handle->LastWriteDataCalled == MP4TRUE)
1.535 + return MP4_ERROR; // WriteData() call has been made before with bytestowrite=0, can not call again.
1.536 +
1.537 + if (bytestowrite != 0)
1.538 + {
1.539 + if (addData(handle, buffer, bytestowrite) == -1)
1.540 + return MP4_OUT_OF_MEMORY;
1.541 + }
1.542 + else
1.543 + handle->LastWriteDataCalled = MP4TRUE;
1.544 +
1.545 +
1.546 + return MP4_OK;
1.547 +}
1.548 +
1.549 +extern EXPORT_C MP4Err MP4ParseGetBufferedBytes(MP4Handle apihandle,
1.550 + mp4_u32 *bytes)
1.551 +{
1.552 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.553 +
1.554 + *bytes = getBufferedBytes(handle);
1.555 +
1.556 + if (handle->file)
1.557 + return MP4_FILE_MODE;
1.558 +
1.559 + return MP4_OK;
1.560 +}
1.561 +
1.562 +extern EXPORT_C MP4Err MP4ParseNextFrameType(MP4Handle apihandle,
1.563 + mp4_u32 *type)
1.564 + {
1.565 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.566 +
1.567 + if (!handle->metaDataComplete)
1.568 + {
1.569 + switch (metaDataAvailable(handle))
1.570 + {
1.571 + case 0:
1.572 + return MP4_NOT_AVAILABLE;
1.573 +
1.574 + case 1:
1.575 + handle->cafError = KErrNone;
1.576 + if (readMetaData(handle) < 0)
1.577 + {
1.578 + // Reading of meta data failed, so free up any allocated memory
1.579 + freeFTYP(handle->ftyp);
1.580 + handle->ftyp = NULL;
1.581 + freeMOOV(handle->moov);
1.582 + handle->moov = NULL;
1.583 +
1.584 + if ( handle->cafError != KErrNone )
1.585 + {
1.586 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.587 + return handle->cafError;
1.588 + }
1.589 + else
1.590 + {
1.591 + return MP4_INVALID_INPUT_STREAM;
1.592 + }
1.593 + }
1.594 + handle->metaDataComplete = MP4TRUE;
1.595 + break;
1.596 +
1.597 + case -2:
1.598 + // Reading of FTYP meta data failed, so free up any allocated memory
1.599 + freeFTYP(handle->ftyp);
1.600 + handle->ftyp = NULL;
1.601 + return MP4_ERROR;
1.602 +
1.603 + case -1:
1.604 + default:
1.605 + return MP4_ERROR;
1.606 + }
1.607 + }
1.608 +
1.609 + /* No audio nor video */
1.610 + if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo))
1.611 + return MP4_ERROR;
1.612 +
1.613 + mp4_u32 audiotype = 0;
1.614 + mp4_i32 audioerror = 0;
1.615 + if (handle->moov->trakAudio)
1.616 + {
1.617 + audioerror = determineAudioType(handle, &audiotype);
1.618 + }
1.619 +
1.620 + mp4_u32 videotype = 0;
1.621 + mp4_i32 videoerror = 0;
1.622 + if (handle->moov->trakVideo)
1.623 + {
1.624 + videoerror = determineVideoType(handle, &videotype);
1.625 + }
1.626 +
1.627 + /* Audio track only */
1.628 + if (handle->moov->trakAudio && !handle->moov->trakVideo)
1.629 + {
1.630 + if (audioerror == 0)
1.631 + {
1.632 + // if audio is of supported type, check if the last audio frame has been
1.633 + // retrieved
1.634 + if (handle->audioLast)
1.635 + {
1.636 + return MP4_NO_FRAME;
1.637 + }
1.638 + else
1.639 + {
1.640 + *type = audiotype;
1.641 + return MP4_OK;
1.642 + }
1.643 + }
1.644 + else
1.645 + {
1.646 + return MP4_ERROR;
1.647 + }
1.648 + }
1.649 +
1.650 + /* Video track only */
1.651 + if (handle->moov->trakVideo && !handle->moov->trakAudio)
1.652 + {
1.653 + if (videoerror == 0)
1.654 + {
1.655 + // if video is of supported type, check if the last video frame has been
1.656 + // retrieved
1.657 + if (handle->videoLast)
1.658 + {
1.659 + return MP4_NO_FRAME;
1.660 + }
1.661 + else
1.662 + {
1.663 + *type = videotype;
1.664 + return MP4_OK;
1.665 + }
1.666 + }
1.667 + else
1.668 + {
1.669 + return MP4_ERROR;
1.670 + }
1.671 + }
1.672 +
1.673 + /* All audio has been read, but there is video left */
1.674 + if (handle->audioLast && !handle->videoLast)
1.675 + {
1.676 + if (videoerror == 0)
1.677 + {
1.678 + *type = videotype;
1.679 + return MP4_OK;
1.680 + }
1.681 + else
1.682 + {
1.683 + return MP4_ERROR;
1.684 + }
1.685 + }
1.686 +
1.687 + /* All video has been read, but there is audio left */
1.688 + if (handle->videoLast && !handle->audioLast)
1.689 + {
1.690 + if (audioerror == 0)
1.691 + {
1.692 + *type = audiotype;
1.693 + return MP4_OK;
1.694 + }
1.695 + else
1.696 + {
1.697 + return MP4_ERROR;
1.698 + }
1.699 + }
1.700 +
1.701 + /* All data has been read */
1.702 + if (handle->audioLast && handle->videoLast)
1.703 + {
1.704 + return MP4_NO_FRAME;
1.705 + }
1.706 +
1.707 + if (handle->audioSampleOffset < handle->videoFrameOffset)
1.708 + {
1.709 + /* Next frame is audio */
1.710 + if (audioerror == 0)
1.711 + {
1.712 + *type = audiotype;
1.713 + return MP4_OK;
1.714 + }
1.715 + else if ( (audioerror == -2) && (videoerror == 0) )
1.716 + {
1.717 + *type = videotype;
1.718 + return MP4_OK;
1.719 + }
1.720 + else
1.721 + {
1.722 + return MP4_ERROR;
1.723 + }
1.724 + }
1.725 + else
1.726 + {
1.727 + /* Next frame is video */
1.728 + if (videoerror == 0)
1.729 + {
1.730 + *type = videotype;
1.731 + return MP4_OK;
1.732 + }
1.733 + else if ( (videoerror == -2) && (audioerror == 0) )
1.734 + {
1.735 + *type = audiotype;
1.736 + return MP4_OK;
1.737 + }
1.738 + else
1.739 + {
1.740 + return MP4_ERROR;
1.741 + }
1.742 + }
1.743 + }
1.744 +
1.745 +extern EXPORT_C MP4Err MP4ParseNextFrameSize(MP4Handle apihandle,
1.746 + mp4_u32 type,
1.747 + mp4_u32 *framesize)
1.748 +{
1.749 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.750 +
1.751 + if (!handle->metaDataComplete)
1.752 + {
1.753 + switch (metaDataAvailable(handle))
1.754 + {
1.755 + case 0:
1.756 +
1.757 + return MP4_NOT_AVAILABLE;
1.758 +
1.759 + case 1:
1.760 + handle->cafError = KErrNone;
1.761 + if (readMetaData(handle) < 0)
1.762 + {
1.763 + // Reading of meta data failed, so free up any allocated memory
1.764 + freeFTYP(handle->ftyp);
1.765 + handle->ftyp = NULL;
1.766 + freeMOOV(handle->moov);
1.767 + handle->moov = NULL;
1.768 +
1.769 + if ( handle->cafError != KErrNone )
1.770 + {
1.771 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.772 + return handle->cafError;
1.773 + }
1.774 + else
1.775 + {
1.776 + return MP4_INVALID_INPUT_STREAM;
1.777 + }
1.778 + }
1.779 +
1.780 + handle->metaDataComplete = MP4TRUE;
1.781 + break;
1.782 +
1.783 + case -2:
1.784 + // Reading of FTYP meta data failed, so free up any allocated memory
1.785 + freeFTYP(handle->ftyp);
1.786 + handle->ftyp = NULL;
1.787 + return MP4_ERROR;
1.788 +
1.789 + case -1:
1.790 + default:
1.791 + return MP4_ERROR;
1.792 + }
1.793 + }
1.794 +
1.795 + switch (type & handle->type)
1.796 + {
1.797 + case MP4_TYPE_MPEG4_VIDEO:
1.798 + case MP4_TYPE_H263_PROFILE_0:
1.799 + case MP4_TYPE_H263_PROFILE_3:
1.800 + case MP4_TYPE_AVC_PROFILE_BASELINE:
1.801 + case MP4_TYPE_AVC_PROFILE_MAIN:
1.802 + case MP4_TYPE_AVC_PROFILE_EXTENDED:
1.803 + case MP4_TYPE_AVC_PROFILE_HIGH:
1.804 +
1.805 + /* There is a next video frame */
1.806 +
1.807 + if (!handle->videoLast)
1.808 + *framesize = handle->videoFrameSize;
1.809 + else
1.810 + {
1.811 + *framesize = 0;
1.812 +
1.813 + return MP4_NO_REQUESTED_FRAME;
1.814 + }
1.815 +
1.816 + break;
1.817 +
1.818 + case MP4_TYPE_MPEG4_AUDIO:
1.819 + case MP4_TYPE_AMR_NB:
1.820 + case MP4_TYPE_AMR_WB:
1.821 + case MP4_TYPE_QCELP_13K:
1.822 +
1.823 + /* There is a next audio frame */
1.824 +
1.825 + if (!handle->audioLast)
1.826 + *framesize = handle->audioSampleSize;
1.827 + else
1.828 + {
1.829 + *framesize = 0;
1.830 +
1.831 + return MP4_NO_REQUESTED_FRAME;
1.832 + }
1.833 +
1.834 + break;
1.835 +
1.836 + case MP4_TYPE_NONE:
1.837 + default:
1.838 +
1.839 + if (type == MP4_TYPE_MPEG4_VIDEO ||
1.840 + type == MP4_TYPE_H263_PROFILE_0 ||
1.841 + type == MP4_TYPE_H263_PROFILE_3 ||
1.842 + type == MP4_TYPE_MPEG4_AUDIO ||
1.843 + type == MP4_TYPE_AMR_NB ||
1.844 + type == MP4_TYPE_AMR_WB ||
1.845 + isAvcVideo(type) ||
1.846 + type == MP4_TYPE_QCELP_13K
1.847 + )
1.848 + return MP4_NO_REQUESTED_FRAME;
1.849 +
1.850 + return MP4_INVALID_TYPE;
1.851 + }
1.852 +
1.853 + return MP4_OK;
1.854 +}
1.855 +
1.856 +extern EXPORT_C MP4Err MP4ParseReadVideoFrame(MP4Handle apihandle,
1.857 + mp4_u8 *buffer,
1.858 + mp4_u32 buffersize,
1.859 + mp4_u32 *framesize,
1.860 + mp4_u32 *timestamp,
1.861 + mp4_bool *keyframe,
1.862 + mp4_u32 *timestamp2)
1.863 +{
1.864 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.865 +
1.866 + if (!handle->metaDataComplete)
1.867 + {
1.868 + switch (metaDataAvailable(handle))
1.869 + {
1.870 + case 0:
1.871 +
1.872 + return MP4_NOT_AVAILABLE;
1.873 +
1.874 + case 1:
1.875 + handle->cafError = KErrNone;
1.876 + if (readMetaData(handle) < 0)
1.877 + {
1.878 + // Reading of meta data failed, so free up any allocated memory
1.879 + freeFTYP(handle->ftyp);
1.880 + handle->ftyp = NULL;
1.881 + freeMOOV(handle->moov);
1.882 + handle->moov = NULL;
1.883 +
1.884 + if ( handle->cafError != KErrNone )
1.885 + {
1.886 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.887 + return handle->cafError;
1.888 + }
1.889 + else
1.890 + {
1.891 + return MP4_INVALID_INPUT_STREAM;
1.892 + }
1.893 + }
1.894 + handle->metaDataComplete = MP4TRUE;
1.895 + break;
1.896 +
1.897 + case -2:
1.898 + // Reading of FTYP meta data failed, so free up any allocated memory
1.899 + freeFTYP(handle->ftyp);
1.900 + handle->ftyp = NULL;
1.901 + return MP4_ERROR;
1.902 +
1.903 + case -1:
1.904 + default:
1.905 + return MP4_ERROR;
1.906 + }
1.907 + }
1.908 +
1.909 + /* Is video available? */
1.910 +
1.911 + if (!((handle->type & MP4_TYPE_MPEG4_VIDEO) ||
1.912 + (handle->type & MP4_TYPE_H263_PROFILE_0) ||
1.913 + (handle->type & MP4_TYPE_H263_PROFILE_3) ||
1.914 + containsAvcVideo( handle->type ) ))
1.915 + return MP4_ERROR;
1.916 +
1.917 + /* Are there samples left? */
1.918 +
1.919 + if (handle->videoLast)
1.920 + return MP4_NO_FRAME;
1.921 +
1.922 + if (!handle->moov)
1.923 + return MP4_ERROR;
1.924 + if (!handle->moov->trakVideo)
1.925 + return MP4_ERROR;
1.926 +
1.927 + switch (fetchVideoFrame(handle, handle->moov->trakVideo, buffer, buffersize, framesize, timestamp, keyframe, timestamp2))
1.928 + {
1.929 + case -1:
1.930 + return MP4_ERROR;
1.931 + case -2:
1.932 + return MP4_BUFFER_TOO_SMALL;
1.933 + case -3:
1.934 + return MP4_NOT_AVAILABLE;
1.935 + case -4:
1.936 + return MP4_INVALID_INPUT_STREAM;
1.937 + default:
1.938 + break;
1.939 + }
1.940 +
1.941 + switch (advanceVideoFrame(handle, handle->moov->trakVideo))
1.942 + {
1.943 + case -1:
1.944 + return MP4_ERROR;
1.945 + case -2:
1.946 + handle->videoLast = MP4TRUE;
1.947 + break;
1.948 + default:
1.949 + break;
1.950 + }
1.951 +
1.952 + return MP4_OK;
1.953 +}
1.954 +
1.955 +extern EXPORT_C MP4Err MP4ParseReadVideoDecoderSpecificInfo(MP4Handle apihandle,
1.956 + mp4_u8 *buffer,
1.957 + mp4_u32 buffersize,
1.958 + mp4_u32 *decspecinfosize)
1.959 + {
1.960 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.961 + if (!handle->metaDataComplete)
1.962 + {
1.963 + switch (metaDataAvailable(handle))
1.964 + {
1.965 + case 0:
1.966 + return MP4_NOT_AVAILABLE;
1.967 +
1.968 + case 1:
1.969 + handle->cafError = KErrNone;
1.970 + if (readMetaData(handle) < 0)
1.971 + {
1.972 + // Reading of meta data failed, so free up any allocated memory
1.973 + freeFTYP(handle->ftyp);
1.974 + handle->ftyp = NULL;
1.975 + freeMOOV(handle->moov);
1.976 + handle->moov = NULL;
1.977 +
1.978 + if ( handle->cafError != KErrNone )
1.979 + {
1.980 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.981 + return handle->cafError;
1.982 + }
1.983 + else
1.984 + {
1.985 + return MP4_INVALID_INPUT_STREAM;
1.986 + }
1.987 + }
1.988 + handle->metaDataComplete = MP4TRUE;
1.989 + break;
1.990 +
1.991 + case -2:
1.992 + // Reading of FTYP meta data failed, so free up any allocated memory
1.993 + freeFTYP(handle->ftyp);
1.994 + handle->ftyp = NULL;
1.995 + return MP4_ERROR;
1.996 +
1.997 + case -1:
1.998 + default:
1.999 + return MP4_ERROR;
1.1000 + }
1.1001 + }
1.1002 +
1.1003 + /* Is video type MPEG or AVC? */
1.1004 + if (!(handle->type & MP4_TYPE_MPEG4_VIDEO) &&
1.1005 + !(containsAvcVideo( handle->type )) )
1.1006 + {
1.1007 + return MP4_ERROR;
1.1008 + }
1.1009 +
1.1010 + if (!handle->moov)
1.1011 + {
1.1012 + return MP4_ERROR;
1.1013 + }
1.1014 + if (!handle->moov->trakVideo)
1.1015 + {
1.1016 + return MP4_ERROR;
1.1017 + }
1.1018 + if (!handle->moov->trakVideo->mdia)
1.1019 + {
1.1020 + return MP4_ERROR;
1.1021 + }
1.1022 + if (!handle->moov->trakVideo->mdia->minf)
1.1023 + {
1.1024 + return MP4_ERROR;
1.1025 + }
1.1026 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.1027 + {
1.1028 + return MP4_ERROR;
1.1029 + }
1.1030 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
1.1031 + {
1.1032 + return MP4_ERROR;
1.1033 + }
1.1034 + if (handle->videoSampleEntryIndex > handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount)
1.1035 + {
1.1036 + return MP4_ERROR;
1.1037 + }
1.1038 +
1.1039 + TInt index = handle->videoSampleEntryIndex - 1;
1.1040 + if (handle->videoSampleEntryIndex == 0)
1.1041 + {
1.1042 + // even though the video sample contains no actual data, if the video sample exist
1.1043 + // and contains decoder specific info, return it anyway
1.1044 + index = 0;
1.1045 + }
1.1046 +
1.1047 + if (handle->type & MP4_TYPE_MPEG4_VIDEO)
1.1048 + {
1.1049 + /* Copy DecoderSpecificInfo into buffer */
1.1050 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index])
1.1051 + {
1.1052 + return MP4_ERROR;
1.1053 + }
1.1054 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd)
1.1055 + {
1.1056 + return MP4_ERROR;
1.1057 + }
1.1058 +
1.1059 + *decspecinfosize = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize;
1.1060 + if (buffersize < handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize)
1.1061 + {
1.1062 + return MP4_BUFFER_TOO_SMALL;
1.1063 + }
1.1064 +
1.1065 + mp4memcpy(buffer,
1.1066 + handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfo,
1.1067 + handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[index]->esd->decSpecificInfoSize);
1.1068 + }
1.1069 + else if ( containsAvcVideo( handle->type ) )
1.1070 + {
1.1071 + /* Copy the AVCDecoderConfigurationRecord into buffer */
1.1072 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index])
1.1073 + {
1.1074 + return MP4_ERROR;
1.1075 + }
1.1076 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc)
1.1077 + {
1.1078 + return MP4_ERROR;
1.1079 + }
1.1080 +
1.1081 + *decspecinfosize = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize;
1.1082 + if (buffersize < handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize)
1.1083 + {
1.1084 + return MP4_BUFFER_TOO_SMALL;
1.1085 + }
1.1086 +
1.1087 + mp4memcpy(buffer,
1.1088 + handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfig,
1.1089 + handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[index]->avcc->avcConfigSize);
1.1090 + }
1.1091 +
1.1092 + return MP4_OK;
1.1093 + }
1.1094 +
1.1095 +extern EXPORT_C MP4Err MP4ParseReadAudioFrames(MP4Handle apihandle,
1.1096 + mp4_u8 *buffer,
1.1097 + mp4_u32 buffersize,
1.1098 + mp4_u32 *audiosize,
1.1099 + mp4_u32 *timestamp,
1.1100 + mp4_u32 *returnedframes,
1.1101 + mp4_u32 *timestamp2)
1.1102 +{
1.1103 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1104 +
1.1105 + if (!handle->metaDataComplete)
1.1106 + {
1.1107 + switch (metaDataAvailable(handle))
1.1108 + {
1.1109 + case 0:
1.1110 + return MP4_NOT_AVAILABLE;
1.1111 +
1.1112 + case 1:
1.1113 + handle->cafError = KErrNone;
1.1114 + if (readMetaData(handle) < 0)
1.1115 + {
1.1116 + // Reading of meta data failed, so free up any allocated memory
1.1117 + freeFTYP(handle->ftyp);
1.1118 + handle->ftyp = NULL;
1.1119 + freeMOOV(handle->moov);
1.1120 + handle->moov = NULL;
1.1121 +
1.1122 + if ( handle->cafError != KErrNone )
1.1123 + {
1.1124 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.1125 + return handle->cafError;
1.1126 + }
1.1127 + else
1.1128 + {
1.1129 + return MP4_INVALID_INPUT_STREAM;
1.1130 + }
1.1131 + }
1.1132 + handle->metaDataComplete = MP4TRUE;
1.1133 + break;
1.1134 +
1.1135 + case -2:
1.1136 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1137 + freeFTYP(handle->ftyp);
1.1138 + handle->ftyp = NULL;
1.1139 + return MP4_ERROR;
1.1140 +
1.1141 + case -1:
1.1142 + default:
1.1143 + return MP4_ERROR;
1.1144 + }
1.1145 + }
1.1146 +
1.1147 + /* Is audio available? */
1.1148 +
1.1149 + if (!((handle->type & MP4_TYPE_MPEG4_AUDIO) ||
1.1150 + (handle->type & MP4_TYPE_AMR_NB) ||
1.1151 + (handle->type & MP4_TYPE_AMR_WB) ||
1.1152 + (handle->type & MP4_TYPE_QCELP_13K)))
1.1153 + return MP4_ERROR;
1.1154 +
1.1155 + /* Are there samples left? */
1.1156 +
1.1157 + if (handle->audioLast)
1.1158 + return MP4_NO_FRAME;
1.1159 +
1.1160 + if (!handle->moov)
1.1161 + return MP4_ERROR;
1.1162 + if (!handle->moov->trakAudio)
1.1163 + return MP4_ERROR;
1.1164 +
1.1165 + switch (fetchAudioSample(handle, handle->moov->trakAudio, buffer, buffersize, audiosize, timestamp, returnedframes, timestamp2))
1.1166 + {
1.1167 + case -1:
1.1168 + return MP4_ERROR;
1.1169 + case -2:
1.1170 + return MP4_BUFFER_TOO_SMALL;
1.1171 + case -3:
1.1172 + return MP4_NOT_AVAILABLE;
1.1173 + case -4:
1.1174 + return MP4_INVALID_INPUT_STREAM;
1.1175 + default:
1.1176 + break;
1.1177 + }
1.1178 +
1.1179 + switch (advanceAudioSample(handle, handle->moov->trakAudio))
1.1180 + {
1.1181 + case -1:
1.1182 + return MP4_ERROR;
1.1183 + case -2:
1.1184 + handle->audioLast = MP4TRUE;
1.1185 + break;
1.1186 + default:
1.1187 + break;
1.1188 + }
1.1189 +
1.1190 + return MP4_OK;
1.1191 +}
1.1192 +
1.1193 +extern EXPORT_C MP4Err MP4ParseReadAudioDecoderSpecificInfo(MP4Handle apihandle,
1.1194 + mp4_u8 *buffer,
1.1195 + mp4_u32 buffersize,
1.1196 + mp4_u32 *decspecinfosize)
1.1197 + {
1.1198 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1199 +
1.1200 + if (!handle->metaDataComplete)
1.1201 + {
1.1202 + switch (metaDataAvailable(handle))
1.1203 + {
1.1204 + case 0:
1.1205 + return MP4_NOT_AVAILABLE;
1.1206 +
1.1207 + case 1:
1.1208 + handle->cafError = KErrNone;
1.1209 + if (readMetaData(handle) < 0)
1.1210 + {
1.1211 + // Reading of meta data failed, so free up any allocated memory
1.1212 + freeFTYP(handle->ftyp);
1.1213 + handle->ftyp = NULL;
1.1214 + freeMOOV(handle->moov);
1.1215 + handle->moov = NULL;
1.1216 +
1.1217 + if ( handle->cafError != KErrNone )
1.1218 + {
1.1219 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.1220 + return handle->cafError;
1.1221 + }
1.1222 + else
1.1223 + {
1.1224 + return MP4_INVALID_INPUT_STREAM;
1.1225 + }
1.1226 + }
1.1227 + handle->metaDataComplete = MP4TRUE;
1.1228 + break;
1.1229 +
1.1230 + case -2:
1.1231 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1232 + freeFTYP(handle->ftyp);
1.1233 + handle->ftyp = NULL;
1.1234 + return MP4_ERROR;
1.1235 +
1.1236 + case -1:
1.1237 + default:
1.1238 + return MP4_ERROR;
1.1239 + }
1.1240 + }
1.1241 +
1.1242 + if (!handle->moov)
1.1243 + {
1.1244 + return MP4_ERROR;
1.1245 + }
1.1246 + if (!handle->moov->trakAudio)
1.1247 + {
1.1248 + return MP4_ERROR;
1.1249 + }
1.1250 + if (!handle->moov->trakAudio->mdia)
1.1251 + {
1.1252 + return MP4_ERROR;
1.1253 + }
1.1254 + if (!handle->moov->trakAudio->mdia->minf)
1.1255 + {
1.1256 + return MP4_ERROR;
1.1257 + }
1.1258 + if (!handle->moov->trakAudio->mdia->minf->stbl)
1.1259 + {
1.1260 + return MP4_ERROR;
1.1261 + }
1.1262 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
1.1263 + {
1.1264 + return MP4_ERROR;
1.1265 + }
1.1266 +
1.1267 +
1.1268 + TInt index = handle->audioSampleEntryIndex - 1;
1.1269 + if (handle->audioSampleEntryIndex == 0)
1.1270 + {
1.1271 + // even though the audio sample contains no actual data, if the audio sample exist
1.1272 + // and contains decoder specific info, return it anyway
1.1273 + index = 0;
1.1274 + }
1.1275 +
1.1276 + /* Audio type */
1.1277 + if ((handle->type & MP4_TYPE_MPEG4_AUDIO) ||
1.1278 + ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)))
1.1279 + {
1.1280 + /* Copy DecoderSpecificInfo into buffer */
1.1281 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index])
1.1282 + {
1.1283 + return MP4_ERROR;
1.1284 + }
1.1285 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd)
1.1286 + {
1.1287 + return MP4_ERROR;
1.1288 + }
1.1289 +
1.1290 + *decspecinfosize = handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize;
1.1291 + if (buffersize < handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize)
1.1292 + {
1.1293 + return MP4_BUFFER_TOO_SMALL;
1.1294 + }
1.1295 +
1.1296 + mp4memcpy(buffer,
1.1297 + handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfo,
1.1298 + handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[index]->esd->decSpecificInfoSize);
1.1299 + }
1.1300 + else if ((handle->type & MP4_TYPE_AMR_NB) ||
1.1301 + (handle->type & MP4_TYPE_AMR_WB) ||
1.1302 + ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)))
1.1303 + {
1.1304 + /* Copy DecoderSpecificInfo into buffer */
1.1305 + if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index] == NULL &&
1.1306 + handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index] == NULL &&
1.1307 + handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index] == NULL)
1.1308 + {
1.1309 + return MP4_ERROR;
1.1310 + }
1.1311 +
1.1312 + if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index])
1.1313 + {
1.1314 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr)
1.1315 + {
1.1316 + return MP4_ERROR;
1.1317 + }
1.1318 +
1.1319 + *decspecinfosize = 9;
1.1320 + if (buffersize < *decspecinfosize)
1.1321 + {
1.1322 + return MP4_BUFFER_TOO_SMALL;
1.1323 + }
1.1324 +
1.1325 + mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->vendor), 4);
1.1326 + mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->decoderVersion), 1);
1.1327 + mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->modeSet), 2);
1.1328 + mp4memcpy(buffer+7, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->modeChangePeriod), 1);
1.1329 + mp4memcpy(buffer+8, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[index]->damr->framesPerSample), 1);
1.1330 + }
1.1331 +
1.1332 + if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index])
1.1333 + {
1.1334 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr)
1.1335 + {
1.1336 + return MP4_ERROR;
1.1337 + }
1.1338 +
1.1339 + *decspecinfosize = 9;
1.1340 + if (buffersize < *decspecinfosize)
1.1341 + {
1.1342 + return MP4_BUFFER_TOO_SMALL;
1.1343 + }
1.1344 +
1.1345 + mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->vendor), 4);
1.1346 + mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->decoderVersion), 1);
1.1347 + mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->modeSet), 2);
1.1348 + mp4memcpy(buffer+7, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->modeChangePeriod), 1);
1.1349 + mp4memcpy(buffer+8, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[index]->damr->framesPerSample), 1);
1.1350 + }
1.1351 +
1.1352 + if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index])
1.1353 + {
1.1354 + if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp)
1.1355 + {
1.1356 + return MP4_ERROR;
1.1357 + }
1.1358 +
1.1359 + *decspecinfosize = 6;
1.1360 + if (buffersize < *decspecinfosize)
1.1361 + {
1.1362 + return MP4_BUFFER_TOO_SMALL;
1.1363 + }
1.1364 +
1.1365 + mp4memcpy(buffer, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->vendor), 4);
1.1366 + mp4memcpy(buffer+4, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->decoderVersion), 1);
1.1367 + mp4memcpy(buffer+5, &(handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[index]->dqcp->framesPerSample), 1);
1.1368 + }
1.1369 + }
1.1370 + else
1.1371 + {
1.1372 + return MP4_ERROR;
1.1373 + }
1.1374 +
1.1375 + return MP4_OK;
1.1376 + }
1.1377 +
1.1378 +extern EXPORT_C MP4Err MP4ParseGetNextVideoTimestamp(MP4Handle apihandle,
1.1379 + mp4_u32 *timestamp,
1.1380 + mp4_u32 *timestamp2)
1.1381 +{
1.1382 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1383 +
1.1384 + if (!handle->metaDataComplete)
1.1385 + {
1.1386 + switch (metaDataAvailable(handle))
1.1387 + {
1.1388 + case 0:
1.1389 +
1.1390 + return MP4_NOT_AVAILABLE;
1.1391 +
1.1392 + case 1:
1.1393 + handle->cafError = KErrNone;
1.1394 + if (readMetaData(handle) < 0)
1.1395 + {
1.1396 + // Reading of meta data failed, so free up any allocated memory
1.1397 + freeFTYP(handle->ftyp);
1.1398 + handle->ftyp = NULL;
1.1399 + freeMOOV(handle->moov);
1.1400 + handle->moov = NULL;
1.1401 +
1.1402 + if ( handle->cafError != KErrNone )
1.1403 + {
1.1404 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.1405 + return handle->cafError;
1.1406 + }
1.1407 + else
1.1408 + {
1.1409 + return MP4_INVALID_INPUT_STREAM;
1.1410 + }
1.1411 + }
1.1412 + handle->metaDataComplete = MP4TRUE;
1.1413 + break;
1.1414 +
1.1415 + case -2:
1.1416 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1417 + freeFTYP(handle->ftyp);
1.1418 + handle->ftyp = NULL;
1.1419 + return MP4_ERROR;
1.1420 +
1.1421 + case -1:
1.1422 + default:
1.1423 + return MP4_ERROR;
1.1424 + }
1.1425 + }
1.1426 +
1.1427 + if (!handle->moov)
1.1428 + return MP4_ERROR;
1.1429 +
1.1430 + if (!handle->moov->trakVideo)
1.1431 + return MP4_ERROR;
1.1432 +
1.1433 + if (!handle->moov->trakVideo->mdia)
1.1434 + return MP4_ERROR;
1.1435 +
1.1436 + if (handle->videoLast)
1.1437 + return MP4_END_OF_VIDEO;
1.1438 +
1.1439 + if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, timestamp, timestamp2) < 0)
1.1440 + return MP4_ERROR;
1.1441 +
1.1442 + switch (advanceVideoFrame(handle, handle->moov->trakVideo))
1.1443 + {
1.1444 + case -1:
1.1445 + return MP4_ERROR;
1.1446 + case -2:
1.1447 + handle->videoLast = MP4TRUE;
1.1448 + break;
1.1449 + default:
1.1450 + break;
1.1451 + }
1.1452 +
1.1453 + return MP4_OK;
1.1454 +}
1.1455 +
1.1456 +extern EXPORT_C MP4Err MP4ParseIsStreamable(MP4Handle apihandle)
1.1457 +{
1.1458 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1459 +
1.1460 + if (!handle->metaDataComplete)
1.1461 + {
1.1462 + switch (metaDataAvailable(handle))
1.1463 + {
1.1464 + case 0:
1.1465 +
1.1466 + return MP4_NOT_AVAILABLE;
1.1467 +
1.1468 + case 1:
1.1469 + handle->cafError = KErrNone;
1.1470 + if (readMetaData(handle) < 0)
1.1471 + {
1.1472 + // Reading of meta data failed, so free up any allocated memory
1.1473 + freeFTYP(handle->ftyp);
1.1474 + handle->ftyp = NULL;
1.1475 + freeMOOV(handle->moov);
1.1476 + handle->moov = NULL;
1.1477 +
1.1478 + if ( handle->cafError != KErrNone )
1.1479 + {
1.1480 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.1481 + return handle->cafError;
1.1482 + }
1.1483 + else
1.1484 + {
1.1485 + return MP4_INVALID_INPUT_STREAM;
1.1486 + }
1.1487 + }
1.1488 + handle->metaDataComplete = MP4TRUE;
1.1489 + break;
1.1490 +
1.1491 + case -2:
1.1492 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1493 + freeFTYP(handle->ftyp);
1.1494 + handle->ftyp = NULL;
1.1495 + return MP4_ERROR;
1.1496 +
1.1497 + case -1:
1.1498 + default:
1.1499 + return MP4_ERROR;
1.1500 + }
1.1501 + }
1.1502 +
1.1503 + /* There is no audio nor video */
1.1504 +
1.1505 + if (!handle->audioSampleNum && !handle->videoSampleNum)
1.1506 + return MP4_ERROR;
1.1507 +
1.1508 + /* There is audio, but no video */
1.1509 +
1.1510 + if (handle->audioSampleNum && !handle->videoSampleNum)
1.1511 + {
1.1512 + if (!handle->moov)
1.1513 + return MP4_ERROR;
1.1514 +
1.1515 + if (!handle->moov->trakAudio)
1.1516 + return MP4_ERROR;
1.1517 +
1.1518 + if (!handle->moov->trakAudio->mdia)
1.1519 + return MP4_ERROR;
1.1520 +
1.1521 + if (!handle->moov->trakAudio->mdia->minf)
1.1522 + return MP4_ERROR;
1.1523 +
1.1524 + if (!handle->moov->trakAudio->mdia->minf->stbl)
1.1525 + return MP4_ERROR;
1.1526 +
1.1527 + if (!handle->moov->trakAudio->mdia->minf->stbl->stco)
1.1528 + return MP4_ERROR;
1.1529 +
1.1530 + if (handle->moov->trakAudio->mdia->minf->stbl->stco->entryCount < 2)
1.1531 + return MP4_OK;
1.1532 +
1.1533 + if (getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 0) <
1.1534 + getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 1))
1.1535 + return MP4_OK;
1.1536 +
1.1537 + return MP4_NOT_STREAMABLE;
1.1538 + }
1.1539 +
1.1540 + /* There is video, but no audio */
1.1541 +
1.1542 + if (handle->videoSampleNum && !handle->audioSampleNum)
1.1543 + {
1.1544 + if (!handle->moov)
1.1545 + return MP4_ERROR;
1.1546 +
1.1547 + if (!handle->moov->trakVideo)
1.1548 + return MP4_ERROR;
1.1549 +
1.1550 + if (!handle->moov->trakVideo->mdia)
1.1551 + return MP4_ERROR;
1.1552 +
1.1553 + if (!handle->moov->trakVideo->mdia->minf)
1.1554 + return MP4_ERROR;
1.1555 +
1.1556 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.1557 + return MP4_ERROR;
1.1558 +
1.1559 + if (!handle->moov->trakVideo->mdia->minf->stbl->stco)
1.1560 + return MP4_ERROR;
1.1561 +
1.1562 + if (handle->moov->trakVideo->mdia->minf->stbl->stco->entryCount < 2)
1.1563 + return MP4_OK;
1.1564 +
1.1565 + if (getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 0) <
1.1566 + getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 1))
1.1567 + return MP4_OK;
1.1568 +
1.1569 + return MP4_NOT_STREAMABLE;
1.1570 + }
1.1571 +
1.1572 + /* There are both audio and video */
1.1573 +
1.1574 + if (handle->videoSampleNum && handle->audioSampleNum)
1.1575 + {
1.1576 + mp4_i64 diff;
1.1577 +
1.1578 +
1.1579 + if (!handle->moov)
1.1580 + return MP4_ERROR;
1.1581 +
1.1582 + if (!handle->moov->trakAudio)
1.1583 + return MP4_ERROR;
1.1584 +
1.1585 + if (!handle->moov->trakAudio->mdia)
1.1586 + return MP4_ERROR;
1.1587 +
1.1588 + if (!handle->moov->trakAudio->mdia->minf)
1.1589 + return MP4_ERROR;
1.1590 +
1.1591 + if (!handle->moov->trakAudio->mdia->minf->stbl)
1.1592 + return MP4_ERROR;
1.1593 +
1.1594 + if (!handle->moov->trakAudio->mdia->minf->stbl->stco)
1.1595 + return MP4_ERROR;
1.1596 +
1.1597 + if (!handle->moov->trakAudio->mdia->minf->stbl->stco->entryCount)
1.1598 + return MP4_ERROR;
1.1599 +
1.1600 + if (!handle->moov->trakVideo)
1.1601 + return MP4_ERROR;
1.1602 +
1.1603 + if (!handle->moov->trakVideo->mdia)
1.1604 + return MP4_ERROR;
1.1605 +
1.1606 + if (!handle->moov->trakVideo->mdia->minf)
1.1607 + return MP4_ERROR;
1.1608 +
1.1609 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.1610 + return MP4_ERROR;
1.1611 +
1.1612 + if (!handle->moov->trakVideo->mdia->minf->stbl->stco)
1.1613 + return MP4_ERROR;
1.1614 +
1.1615 + if (!handle->moov->trakVideo->mdia->minf->stbl->stco->entryCount)
1.1616 + return MP4_ERROR;
1.1617 +
1.1618 + diff = getChunkOffset(handle->moov->trakAudio->mdia->minf->stbl, 0) -
1.1619 + getChunkOffset(handle->moov->trakVideo->mdia->minf->stbl, 0);
1.1620 +
1.1621 + /* If the distance between 1st audio and video chunk offsets is larger
1.1622 + than 50000, MP4 is not streamable. */
1.1623 +
1.1624 + if (diff < -50000 || diff > 50000)
1.1625 + return MP4_NOT_STREAMABLE;
1.1626 +
1.1627 + return MP4_OK;
1.1628 + }
1.1629 +
1.1630 + return MP4_OK;
1.1631 +}
1.1632 +
1.1633 +extern EXPORT_C MP4Err MP4ParseSeek(MP4Handle apihandle,
1.1634 + mp4_u32 position,
1.1635 + mp4_u32 *audioPosition,
1.1636 + mp4_u32 *videoPosition,
1.1637 + mp4_bool keyframe)
1.1638 +{
1.1639 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1640 + if (!handle->metaDataComplete)
1.1641 + {
1.1642 + switch (metaDataAvailable(handle))
1.1643 + {
1.1644 + case 0:
1.1645 + return MP4_NOT_AVAILABLE;
1.1646 + case 1:
1.1647 + handle->cafError = KErrNone;
1.1648 + if (readMetaData(handle) < 0)
1.1649 + {
1.1650 + // Reading of meta data failed, so free up any allocated memory
1.1651 + freeFTYP(handle->ftyp);
1.1652 + handle->ftyp = NULL;
1.1653 + freeMOOV(handle->moov);
1.1654 + handle->moov = NULL;
1.1655 +
1.1656 + if ( handle->cafError != KErrNone )
1.1657 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.1658 + return handle->cafError;
1.1659 + }
1.1660 + else
1.1661 + {
1.1662 + return MP4_INVALID_INPUT_STREAM;
1.1663 + }
1.1664 + }
1.1665 + handle->metaDataComplete = MP4TRUE;
1.1666 + break;
1.1667 +
1.1668 + case -2:
1.1669 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1670 + freeFTYP(handle->ftyp);
1.1671 + handle->ftyp = NULL;
1.1672 + return MP4_ERROR;
1.1673 +
1.1674 + case -1:
1.1675 + default:
1.1676 + return MP4_ERROR;
1.1677 + }
1.1678 + }
1.1679 +
1.1680 + if (!handle->moov)
1.1681 + return MP4_ERROR;
1.1682 +
1.1683 + handle->audioLast = MP4FALSE;
1.1684 + handle->videoLast = MP4FALSE;
1.1685 +
1.1686 + /* There is no audio nor video */
1.1687 +
1.1688 + if (!handle->audioSampleNum && !handle->videoSampleNum)
1.1689 + return MP4_ERROR;
1.1690 +
1.1691 + /* There is only audio */
1.1692 +
1.1693 + if (handle->audioSampleNum && !handle->videoSampleNum)
1.1694 + {
1.1695 + mp4_u32 audioSample;
1.1696 +
1.1697 + if (!handle->moov->trakAudio)
1.1698 + return MP4_ERROR;
1.1699 + if (!handle->moov->trakAudio->mdia)
1.1700 + return MP4_ERROR;
1.1701 +
1.1702 + if (convertTimeToSample(handle, handle->moov->trakAudio, position, &audioSample) < 0)
1.1703 + return MP4_CANT_SEEK;
1.1704 +
1.1705 + if (goToAudioSample(handle, handle->moov->trakAudio, audioSample) < 0)
1.1706 + return MP4_ERROR;
1.1707 +
1.1708 + if (convertAudioSampleToTime(handle, handle->moov->trakAudio->mdia, audioPosition, NULL) < 0)
1.1709 + return MP4_ERROR;
1.1710 +
1.1711 + if (handle->file)
1.1712 + {
1.1713 + handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
1.1714 + }
1.1715 + else
1.1716 + {
1.1717 + // check if there is enough data in the buffers
1.1718 + if (handle->audioSampleOffset + handle->audioSampleSize - 1 > getCumulativeBufferedBytes(handle))
1.1719 + {
1.1720 + if (handle->LastWriteDataCalled)
1.1721 + {
1.1722 + // user has indicated that no more data will be available
1.1723 + return MP4_CANT_SEEK;
1.1724 + }
1.1725 + else
1.1726 + {
1.1727 + // signal to user that more data needed
1.1728 + return MP4_NOT_AVAILABLE;
1.1729 + }
1.1730 + }
1.1731 + else if (handle->audioSampleOffset < handle->absPosition)
1.1732 + {
1.1733 + handle->absPosition = handle->audioSampleOffset;
1.1734 + }
1.1735 + }
1.1736 +
1.1737 + return MP4_OK;
1.1738 + }
1.1739 +
1.1740 + /* There is only video */
1.1741 + if (handle->videoSampleNum && !handle->audioSampleNum)
1.1742 + {
1.1743 + mp4_u32 videoSample;
1.1744 + mp4_u32 newVideoSample;
1.1745 +
1.1746 + if (!handle->moov->trakVideo)
1.1747 + return MP4_ERROR;
1.1748 + if (!handle->moov->trakVideo->mdia)
1.1749 + return MP4_ERROR;
1.1750 +
1.1751 + if (convertTimeToSample(handle, handle->moov->trakVideo, position, &videoSample) < 0)
1.1752 + return MP4_CANT_SEEK;
1.1753 +
1.1754 + if (keyframe)
1.1755 + {
1.1756 + if (findVideoKeyFrame(handle, handle->moov->trakVideo, videoSample, &newVideoSample) < 0)
1.1757 + {
1.1758 + return MP4_CANT_SEEK;
1.1759 + }
1.1760 + videoSample = newVideoSample;
1.1761 + }
1.1762 +
1.1763 + if (goToVideoSample(handle, handle->moov->trakVideo, videoSample) < 0)
1.1764 + {
1.1765 + return MP4_ERROR;
1.1766 + }
1.1767 +
1.1768 + if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, videoPosition, NULL) < 0)
1.1769 + {
1.1770 + return MP4_ERROR;
1.1771 + }
1.1772 +
1.1773 + if (handle->file)
1.1774 + {
1.1775 + handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
1.1776 + }
1.1777 + else // input is a stream
1.1778 + {
1.1779 + // check if there is enough data in the buffers
1.1780 + if (handle->videoFrameOffset + handle->videoFrameSize > getCumulativeBufferedBytes(handle))
1.1781 + {
1.1782 + if (handle->LastWriteDataCalled)
1.1783 + {
1.1784 + // user has indicated that no more data will be available
1.1785 + return MP4_CANT_SEEK;
1.1786 + }
1.1787 + else
1.1788 + {
1.1789 + // signal to user that more data needed
1.1790 + return MP4_NOT_AVAILABLE;
1.1791 + }
1.1792 + }
1.1793 + else
1.1794 + {
1.1795 + handle->absPosition = handle->videoFrameOffset;
1.1796 + }
1.1797 + }
1.1798 +
1.1799 + return MP4_OK;
1.1800 + }
1.1801 +
1.1802 + /* There is audio and video */
1.1803 +
1.1804 + if (handle->videoSampleNum && handle->audioSampleNum)
1.1805 + {
1.1806 + mp4_u32 audioSample;
1.1807 + mp4_u32 videoSample;
1.1808 + mp4_u32 newVideoSample;
1.1809 +
1.1810 +
1.1811 + if (!handle->moov->trakAudio)
1.1812 + return MP4_ERROR;
1.1813 + if (!handle->moov->trakAudio->mdia)
1.1814 + return MP4_ERROR;
1.1815 + if (!handle->moov->trakVideo)
1.1816 + return MP4_ERROR;
1.1817 + if (!handle->moov->trakVideo->mdia)
1.1818 + return MP4_ERROR;
1.1819 +
1.1820 + if (convertTimeToSample(handle, handle->moov->trakVideo, position, &videoSample) < 0)
1.1821 + return MP4_CANT_SEEK;
1.1822 +
1.1823 + if (keyframe)
1.1824 + {
1.1825 + if (findVideoKeyFrame(handle, handle->moov->trakVideo, videoSample, &newVideoSample) < 0)
1.1826 + return MP4_CANT_SEEK;
1.1827 +
1.1828 + videoSample = newVideoSample;
1.1829 + }
1.1830 +
1.1831 + if (goToVideoSample(handle, handle->moov->trakVideo, videoSample) < 0)
1.1832 + return MP4_ERROR;
1.1833 +
1.1834 + if (convertVideoSampleToTime(handle, handle->moov->trakVideo->mdia, videoPosition, NULL) < 0)
1.1835 + return MP4_ERROR;
1.1836 +
1.1837 + if (handle->file)
1.1838 + {
1.1839 + handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
1.1840 + }
1.1841 + else // input is a stream
1.1842 + {
1.1843 + // check if there is enough data in the buffers
1.1844 + if (handle->videoFrameOffset + handle->videoFrameSize > getCumulativeBufferedBytes(handle))
1.1845 + {
1.1846 + if (handle->LastWriteDataCalled)
1.1847 + {
1.1848 + // user has indicated that no more data will be available
1.1849 + return MP4_CANT_SEEK;
1.1850 + }
1.1851 + else
1.1852 + {
1.1853 + // signal to user that more data needed
1.1854 + return MP4_NOT_AVAILABLE;
1.1855 + }
1.1856 + }
1.1857 + else
1.1858 + {
1.1859 + handle->absPosition = handle->videoFrameOffset;
1.1860 + }
1.1861 + }
1.1862 +
1.1863 + /* Audio */
1.1864 +
1.1865 + if (convertTimeToSample(handle, handle->moov->trakAudio, *videoPosition, &audioSample) < 0)
1.1866 + return MP4_CANT_SEEK;
1.1867 +
1.1868 + if (goToAudioSample(handle, handle->moov->trakAudio, audioSample) < 0)
1.1869 + return MP4_ERROR;
1.1870 +
1.1871 + if (convertAudioSampleToTime(handle, handle->moov->trakAudio->mdia, audioPosition, NULL) < 0)
1.1872 + return MP4_ERROR;
1.1873 +
1.1874 + if (handle->file)
1.1875 + {
1.1876 + if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile)
1.1877 + {
1.1878 + handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
1.1879 + }
1.1880 + }
1.1881 + else // input is a stream
1.1882 + {
1.1883 + // check if there is enough data in the buffers
1.1884 + if (handle->audioSampleOffset + handle->audioSampleSize - 1 > getCumulativeBufferedBytes(handle))
1.1885 + {
1.1886 + if (handle->LastWriteDataCalled)
1.1887 + {
1.1888 + // user has indicated that no more data will be available
1.1889 + return MP4_CANT_SEEK;
1.1890 + }
1.1891 + else
1.1892 + {
1.1893 + // signal to user that more data needed
1.1894 + return MP4_NOT_AVAILABLE;
1.1895 + }
1.1896 + }
1.1897 + else if (handle->audioSampleOffset < handle->absPosition)
1.1898 + {
1.1899 + handle->absPosition = handle->audioSampleOffset;
1.1900 + }
1.1901 + }
1.1902 +
1.1903 + return MP4_OK;
1.1904 + }
1.1905 +
1.1906 + return MP4_OK;
1.1907 +}
1.1908 +
1.1909 +extern EXPORT_C MP4Err MP4ParseIsFrameAvailable(MP4Handle apihandle,
1.1910 + mp4_u32 type)
1.1911 +{
1.1912 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.1913 + if (!handle->metaDataComplete)
1.1914 + {
1.1915 + switch (metaDataAvailable(handle))
1.1916 + {
1.1917 + case 0:
1.1918 + return MP4_NOT_AVAILABLE;
1.1919 + case 1:
1.1920 + handle->cafError = KErrNone;
1.1921 + if (readMetaData(handle) < 0)
1.1922 + {
1.1923 + // Reading of meta data failed, so free up any allocated memory
1.1924 + freeFTYP(handle->ftyp);
1.1925 + handle->ftyp = NULL;
1.1926 + freeMOOV(handle->moov);
1.1927 + handle->moov = NULL;
1.1928 +
1.1929 + if ( handle->cafError != KErrNone )
1.1930 + {
1.1931 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.1932 +
1.1933 + return handle->cafError;
1.1934 + }
1.1935 + else
1.1936 + {
1.1937 + return MP4_INVALID_INPUT_STREAM;
1.1938 + }
1.1939 + }
1.1940 + handle->metaDataComplete = MP4TRUE;
1.1941 + break;
1.1942 +
1.1943 + case -2:
1.1944 + // Reading of FTYP meta data failed, so free up any allocated memory
1.1945 + freeFTYP(handle->ftyp);
1.1946 + handle->ftyp = NULL;
1.1947 + return MP4_ERROR;
1.1948 +
1.1949 + case -1:
1.1950 + default:
1.1951 + return MP4_ERROR;
1.1952 + }
1.1953 + }
1.1954 +
1.1955 + switch (type & handle->type)
1.1956 + {
1.1957 + case MP4_TYPE_MPEG4_VIDEO:
1.1958 + case MP4_TYPE_H263_PROFILE_0:
1.1959 + case MP4_TYPE_H263_PROFILE_3:
1.1960 + case MP4_TYPE_AVC_PROFILE_BASELINE:
1.1961 + case MP4_TYPE_AVC_PROFILE_MAIN:
1.1962 + case MP4_TYPE_AVC_PROFILE_EXTENDED:
1.1963 + case MP4_TYPE_AVC_PROFILE_HIGH:
1.1964 +
1.1965 + /* There is no frame available if last sample has been reached */
1.1966 +
1.1967 + if (handle->videoLast)
1.1968 + return MP4_NO_REQUESTED_FRAME;
1.1969 +
1.1970 + /* Input in a file => it is available */
1.1971 +
1.1972 + if (handle->file)
1.1973 + return MP4_OK;
1.1974 +
1.1975 + /* If frame has been buffered, it is available */
1.1976 +
1.1977 + if (handle->videoFrameOffset + handle->videoFrameSize <=
1.1978 + getCumulativeBufferedBytes(handle))
1.1979 + return MP4_OK;
1.1980 + else
1.1981 + return MP4_NOT_AVAILABLE;
1.1982 +
1.1983 + case MP4_TYPE_MPEG4_AUDIO:
1.1984 + case MP4_TYPE_AMR_NB:
1.1985 + case MP4_TYPE_AMR_WB:
1.1986 + case MP4_TYPE_QCELP_13K:
1.1987 +
1.1988 + /* There is no frame available if last sample has been reached */
1.1989 +
1.1990 + if (handle->audioLast)
1.1991 + return MP4_NO_REQUESTED_FRAME;
1.1992 +
1.1993 + /* Input in a file => it is available */
1.1994 +
1.1995 + if (handle->file)
1.1996 + return MP4_OK;
1.1997 +
1.1998 + /* If frame has been buffered, it is available */
1.1999 +
1.2000 + if (handle->audioSampleOffset + handle->audioSampleSize <=
1.2001 + getCumulativeBufferedBytes(handle))
1.2002 + return MP4_OK;
1.2003 + else
1.2004 + return MP4_NOT_AVAILABLE;
1.2005 +
1.2006 + case MP4_TYPE_NONE:
1.2007 + default:
1.2008 +
1.2009 + return MP4_NO_REQUESTED_FRAME;
1.2010 + }
1.2011 +}
1.2012 +
1.2013 +extern EXPORT_C MP4Err MP4ParseGetLastPosition(MP4Handle apihandle,
1.2014 + mp4_u32 *position)
1.2015 +{
1.2016 + return MP4ParseGetLastPosition64(apihandle, (mp4_u64 *)position);
1.2017 +}
1.2018 +
1.2019 +extern EXPORT_C MP4Err MP4ParseGetLastPosition64(MP4Handle apihandle,
1.2020 + mp4_u64 *position)
1.2021 +{
1.2022 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2023 + if (!handle->file)
1.2024 + {
1.2025 + *position = handle->absPosition; // return the latest accessed absolute byte location of the stream.
1.2026 + return MP4_OK;
1.2027 + }
1.2028 + *position = handle->lastAccessedPosInFile;
1.2029 +
1.2030 + return MP4_OK;
1.2031 +}
1.2032 +
1.2033 +extern EXPORT_C MP4Err MP4ParseGetNumberOfVideoFrames(MP4Handle apihandle,
1.2034 + mp4_u32 *numberOfFrames)
1.2035 +{
1.2036 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2037 + if (!handle->metaDataComplete)
1.2038 + {
1.2039 + switch (metaDataAvailable(handle))
1.2040 + {
1.2041 + case 0:
1.2042 + return MP4_NOT_AVAILABLE;
1.2043 + case 1:
1.2044 + handle->cafError = KErrNone;
1.2045 + if (readMetaData(handle) < 0)
1.2046 + {
1.2047 + // Reading of meta data failed, so free up any allocated memory
1.2048 + freeFTYP(handle->ftyp);
1.2049 + handle->ftyp = NULL;
1.2050 + freeMOOV(handle->moov);
1.2051 + handle->moov = NULL;
1.2052 +
1.2053 + if ( handle->cafError != KErrNone )
1.2054 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2055 + return handle->cafError;
1.2056 + }
1.2057 + else
1.2058 + {
1.2059 + return MP4_INVALID_INPUT_STREAM;
1.2060 + }
1.2061 + }
1.2062 + handle->metaDataComplete = MP4TRUE;
1.2063 + break;
1.2064 +
1.2065 + case -2:
1.2066 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2067 + freeFTYP(handle->ftyp);
1.2068 + handle->ftyp = NULL;
1.2069 + return MP4_ERROR;
1.2070 +
1.2071 + case -1:
1.2072 + default:
1.2073 + return MP4_ERROR;
1.2074 + }
1.2075 + }
1.2076 +
1.2077 + if (!handle->moov)
1.2078 + return MP4_ERROR;
1.2079 +
1.2080 + if (handle->moov->trakVideo)
1.2081 + {
1.2082 + if (!handle->moov->trakVideo->mdia)
1.2083 + return MP4_ERROR;
1.2084 +
1.2085 + if (!handle->moov->trakVideo->mdia->minf)
1.2086 + return MP4_ERROR;
1.2087 +
1.2088 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2089 + return MP4_ERROR;
1.2090 +
1.2091 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
1.2092 + return MP4_ERROR;
1.2093 + }
1.2094 + else
1.2095 + {
1.2096 + return MP4_ERROR;
1.2097 + }
1.2098 +
1.2099 + *numberOfFrames = handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount;
1.2100 + return MP4_OK;
1.2101 +}
1.2102 +
1.2103 +extern EXPORT_C MP4Err MP4ParseGetVideoFrameSize(MP4Handle apihandle,
1.2104 + mp4_u32 index,
1.2105 + mp4_u32 *frameSize)
1.2106 + {
1.2107 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2108 + if (!handle->metaDataComplete)
1.2109 + {
1.2110 + switch (metaDataAvailable(handle))
1.2111 + {
1.2112 + case 0:
1.2113 + return MP4_NOT_AVAILABLE;
1.2114 + case 1:
1.2115 + handle->cafError = KErrNone;
1.2116 + if (readMetaData(handle) < 0)
1.2117 + {
1.2118 + // Reading of meta data failed, so free up any allocated memory
1.2119 + freeFTYP(handle->ftyp);
1.2120 + handle->ftyp = NULL;
1.2121 + freeMOOV(handle->moov);
1.2122 + handle->moov = NULL;
1.2123 +
1.2124 + if ( handle->cafError != KErrNone )
1.2125 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2126 + return handle->cafError;
1.2127 + }
1.2128 + else
1.2129 + {
1.2130 + return MP4_INVALID_INPUT_STREAM;
1.2131 + }
1.2132 + }
1.2133 + handle->metaDataComplete = MP4TRUE;
1.2134 + break;
1.2135 +
1.2136 + case -2:
1.2137 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2138 + freeFTYP(handle->ftyp);
1.2139 + handle->ftyp = NULL;
1.2140 + return MP4_ERROR;
1.2141 +
1.2142 + case -1:
1.2143 + default:
1.2144 + return MP4_ERROR;
1.2145 + }
1.2146 + }
1.2147 +
1.2148 + if (!handle->moov)
1.2149 + return MP4_ERROR;
1.2150 +
1.2151 + if (handle->moov->trakVideo)
1.2152 + {
1.2153 + if (!handle->moov->trakVideo->mdia)
1.2154 + return MP4_ERROR;
1.2155 +
1.2156 + if (!handle->moov->trakVideo->mdia->minf)
1.2157 + return MP4_ERROR;
1.2158 +
1.2159 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2160 + return MP4_ERROR;
1.2161 +
1.2162 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
1.2163 + return MP4_ERROR;
1.2164 +
1.2165 + // ensure the index entered is within bound
1.2166 + if (index >= handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount)
1.2167 + return MP4_ERROR;
1.2168 + }
1.2169 + else
1.2170 + {
1.2171 + return MP4_ERROR;
1.2172 + }
1.2173 +
1.2174 + *frameSize = handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[index];
1.2175 + return MP4_OK;
1.2176 + }
1.2177 +
1.2178 +extern EXPORT_C MP4Err MP4ParseGetVideoFrameStartTime(MP4Handle apihandle,
1.2179 + mp4_u32 index,
1.2180 + mp4_u32 *timestamp,
1.2181 + mp4_u32 *timestampms)
1.2182 +{
1.2183 + mp4_u32 tmptime=0;
1.2184 + mp4_u32 sample=0;
1.2185 + mp4_u32 entry=0;
1.2186 + mp4_u32 videoSampleNumber = index+1;
1.2187 +
1.2188 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2189 + if (!handle->metaDataComplete)
1.2190 + {
1.2191 + switch (metaDataAvailable(handle))
1.2192 + {
1.2193 + case 0:
1.2194 + return MP4_NOT_AVAILABLE;
1.2195 + case 1:
1.2196 + handle->cafError = KErrNone;
1.2197 + if (readMetaData(handle) < 0)
1.2198 + {
1.2199 + // Reading of meta data failed, so free up any allocated memory
1.2200 + freeFTYP(handle->ftyp);
1.2201 + handle->ftyp = NULL;
1.2202 + freeMOOV(handle->moov);
1.2203 + handle->moov = NULL;
1.2204 +
1.2205 + if ( handle->cafError != KErrNone )
1.2206 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2207 + return handle->cafError;
1.2208 + }
1.2209 + else
1.2210 + {
1.2211 + return MP4_INVALID_INPUT_STREAM;
1.2212 + }
1.2213 + }
1.2214 + handle->metaDataComplete = MP4TRUE;
1.2215 + break;
1.2216 +
1.2217 + case -2:
1.2218 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2219 + freeFTYP(handle->ftyp);
1.2220 + handle->ftyp = NULL;
1.2221 + return MP4_ERROR;
1.2222 +
1.2223 + case -1:
1.2224 + default:
1.2225 + return MP4_ERROR;
1.2226 + }
1.2227 + }
1.2228 +
1.2229 + if (!handle->moov)
1.2230 + {
1.2231 + return MP4_ERROR;
1.2232 + }
1.2233 +
1.2234 + if (handle->moov->trakVideo)
1.2235 + {
1.2236 + if (!handle->moov->trakVideo->mdia)
1.2237 + return MP4_ERROR;
1.2238 +
1.2239 + if (!handle->moov->trakVideo->mdia->minf)
1.2240 + return MP4_ERROR;
1.2241 +
1.2242 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2243 + return MP4_ERROR;
1.2244 +
1.2245 + if (!handle->moov->trakVideo->mdia->minf->stbl->stts)
1.2246 + return MP4_ERROR;
1.2247 + }
1.2248 + else
1.2249 + {
1.2250 + return MP4_ERROR;
1.2251 + }
1.2252 +
1.2253 + for (;;)
1.2254 + {
1.2255 + if (sample + handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry] < videoSampleNumber)
1.2256 + {
1.2257 + sample += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];
1.2258 + tmptime += (handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry] *
1.2259 + handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry]);
1.2260 + entry++;
1.2261 + if (entry == handle->moov->trakVideo->mdia->minf->stbl->stts->entryCount)
1.2262 + return MP4_ERROR;
1.2263 + }
1.2264 + else
1.2265 + {
1.2266 + tmptime += ((videoSampleNumber - sample - 1) * handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry]);
1.2267 + break;
1.2268 + }
1.2269 + }
1.2270 + if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
1.2271 + {
1.2272 + return MP4_ERROR;
1.2273 + }
1.2274 +
1.2275 + *timestamp = tmptime;
1.2276 +
1.2277 + *timestampms =(mp4_u32)((mp4_double)tmptime * (mp4_double)1000 /
1.2278 + (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale + (mp4_double)0.5);
1.2279 +
1.2280 + return MP4_OK;
1.2281 +}
1.2282 +
1.2283 +extern EXPORT_C MP4Err MP4ParseGetVideoFrameType(MP4Handle apihandle,
1.2284 + mp4_u32 index,
1.2285 + mp4_bool *frametype)
1.2286 + {
1.2287 + mp4_u32 i;
1.2288 + mp4_u32 videoSampleNumber = index+1;
1.2289 + mp4_bool keyFrame = MP4FALSE;
1.2290 +
1.2291 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2292 + if (!handle->metaDataComplete)
1.2293 + {
1.2294 + switch (metaDataAvailable(handle))
1.2295 + {
1.2296 + case 0:
1.2297 + return MP4_NOT_AVAILABLE;
1.2298 + case 1:
1.2299 + handle->cafError = KErrNone;
1.2300 + if (readMetaData(handle) < 0)
1.2301 + {
1.2302 + // Reading of meta data failed, so free up any allocated memory
1.2303 + freeFTYP(handle->ftyp);
1.2304 + handle->ftyp = NULL;
1.2305 + freeMOOV(handle->moov);
1.2306 + handle->moov = NULL;
1.2307 +
1.2308 + if ( handle->cafError != KErrNone )
1.2309 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2310 + return handle->cafError;
1.2311 + }
1.2312 + else
1.2313 + {
1.2314 + return MP4_INVALID_INPUT_STREAM;
1.2315 + }
1.2316 + }
1.2317 + handle->metaDataComplete = MP4TRUE;
1.2318 + break;
1.2319 +
1.2320 + case -2:
1.2321 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2322 + freeFTYP(handle->ftyp);
1.2323 + handle->ftyp = NULL;
1.2324 + return MP4_ERROR;
1.2325 +
1.2326 + case -1:
1.2327 + default:
1.2328 + return MP4_ERROR;
1.2329 + }
1.2330 + }
1.2331 +
1.2332 + if (!handle->moov)
1.2333 + return MP4_ERROR;
1.2334 +
1.2335 + if (handle->moov->trakVideo)
1.2336 + {
1.2337 + if (!handle->moov->trakVideo->mdia)
1.2338 + return MP4_ERROR;
1.2339 +
1.2340 + if (!handle->moov->trakVideo->mdia->minf)
1.2341 + return MP4_ERROR;
1.2342 +
1.2343 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2344 + return MP4_ERROR;
1.2345 +
1.2346 + if (!handle->moov->trakVideo->mdia->minf->stbl->stss)
1.2347 + return MP4_ERROR;
1.2348 +
1.2349 + // if the video frame index is out of bounds
1.2350 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsz ||
1.2351 + videoSampleNumber > handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount)
1.2352 + return MP4_ERROR;
1.2353 + }
1.2354 + else
1.2355 + {
1.2356 + return MP4_ERROR;
1.2357 + }
1.2358 +
1.2359 + for (i=0; i < handle->moov->trakVideo->mdia->minf->stbl->stss->entryCount; i++)
1.2360 + {
1.2361 + if (handle->moov->trakVideo->mdia->minf->stbl->stss->sampleNumber[i] == videoSampleNumber)
1.2362 + {
1.2363 + keyFrame = MP4TRUE;
1.2364 + break;
1.2365 + }
1.2366 + }
1.2367 +
1.2368 + *frametype = keyFrame;
1.2369 + return MP4_OK;
1.2370 +}
1.2371 +
1.2372 +extern EXPORT_C MP4Err MP4ParseGetVideoSampleEntryIndex(MP4Handle apihandle, mp4_u32 *videosampleentryindex)
1.2373 +{
1.2374 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2375 + if (!handle->metaDataComplete)
1.2376 + {
1.2377 + switch (metaDataAvailable(handle))
1.2378 + {
1.2379 + case 0:
1.2380 + return MP4_NOT_AVAILABLE;
1.2381 + case 1:
1.2382 + handle->cafError = KErrNone;
1.2383 + if (readMetaData(handle) < 0)
1.2384 + {
1.2385 + // Reading of meta data failed, so free up any allocated memory
1.2386 + freeFTYP(handle->ftyp);
1.2387 + handle->ftyp = NULL;
1.2388 + freeMOOV(handle->moov);
1.2389 + handle->moov = NULL;
1.2390 +
1.2391 + if ( handle->cafError != KErrNone )
1.2392 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2393 + return handle->cafError;
1.2394 + }
1.2395 + else
1.2396 + {
1.2397 + return MP4_INVALID_INPUT_STREAM;
1.2398 + }
1.2399 + }
1.2400 + handle->metaDataComplete = MP4TRUE;
1.2401 + break;
1.2402 +
1.2403 + case -2:
1.2404 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2405 + freeFTYP(handle->ftyp);
1.2406 + handle->ftyp = NULL;
1.2407 + return MP4_ERROR;
1.2408 +
1.2409 + case -1:
1.2410 + default:
1.2411 + return MP4_ERROR;
1.2412 + }
1.2413 + }
1.2414 +
1.2415 + if (!handle->moov->trakVideo)
1.2416 + return MP4_ERROR;
1.2417 + if (!handle->moov->trakVideo->mdia)
1.2418 + return MP4_ERROR;
1.2419 +
1.2420 + if (handle->videoSampleEntryIndex == 0) /* can't be zero. Sample Entry index must be at least 1*/
1.2421 + return MP4_ERROR;
1.2422 + else
1.2423 + *videosampleentryindex = handle->videoSampleEntryIndex;
1.2424 +
1.2425 + return MP4_OK;
1.2426 +}
1.2427 +
1.2428 +extern EXPORT_C MP4Err MP4ParseGetAudioSampleEntryIndex(MP4Handle apihandle, mp4_u32 *audiosampleentryindex)
1.2429 +{
1.2430 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2431 + if (!handle->metaDataComplete)
1.2432 + {
1.2433 + switch (metaDataAvailable(handle))
1.2434 + {
1.2435 + case 0:
1.2436 + return MP4_NOT_AVAILABLE;
1.2437 + case 1:
1.2438 + handle->cafError = KErrNone;
1.2439 + if (readMetaData(handle) < 0)
1.2440 + {
1.2441 + // Reading of meta data failed, so free up any allocated memory
1.2442 + freeFTYP(handle->ftyp);
1.2443 + handle->ftyp = NULL;
1.2444 + freeMOOV(handle->moov);
1.2445 + handle->moov = NULL;
1.2446 +
1.2447 + if ( handle->cafError != KErrNone )
1.2448 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2449 + return handle->cafError;
1.2450 + }
1.2451 + else
1.2452 + {
1.2453 + return MP4_INVALID_INPUT_STREAM;
1.2454 + }
1.2455 + }
1.2456 + handle->metaDataComplete = MP4TRUE;
1.2457 + break;
1.2458 +
1.2459 + case -2:
1.2460 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2461 + freeFTYP(handle->ftyp);
1.2462 + handle->ftyp = NULL;
1.2463 + return MP4_ERROR;
1.2464 +
1.2465 + case -1:
1.2466 + default:
1.2467 + return MP4_ERROR;
1.2468 + }
1.2469 + }
1.2470 +
1.2471 + if (!handle->moov->trakAudio)
1.2472 + return MP4_ERROR;
1.2473 + if (!handle->moov->trakAudio->mdia)
1.2474 + return MP4_ERROR;
1.2475 +
1.2476 + if (handle->audioSampleEntryIndex == 0) /* can't be zero. Sample Entry index must be at least 1*/
1.2477 + return MP4_ERROR;
1.2478 + else
1.2479 + *audiosampleentryindex = handle->audioSampleEntryIndex;
1.2480 +
1.2481 + return MP4_OK;
1.2482 +}
1.2483 +
1.2484 +extern EXPORT_C MP4Err MP4ParseGetQCELPStorageMode(MP4Handle apihandle, mp4_u8 *qcelpStorageMode)
1.2485 +{
1.2486 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2487 + if (!handle->metaDataComplete)
1.2488 + {
1.2489 + switch (metaDataAvailable(handle))
1.2490 + {
1.2491 + case 0:
1.2492 + return MP4_NOT_AVAILABLE;
1.2493 + case 1:
1.2494 + handle->cafError = KErrNone;
1.2495 + if (readMetaData(handle) < 0)
1.2496 + {
1.2497 + // Reading of meta data failed, so free up any allocated memory
1.2498 + freeFTYP(handle->ftyp);
1.2499 + handle->ftyp = NULL;
1.2500 + freeMOOV(handle->moov);
1.2501 + handle->moov = NULL;
1.2502 +
1.2503 + if ( handle->cafError != KErrNone )
1.2504 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2505 + return handle->cafError;
1.2506 + }
1.2507 + else
1.2508 + {
1.2509 + return MP4_INVALID_INPUT_STREAM;
1.2510 + }
1.2511 + }
1.2512 + handle->metaDataComplete = MP4TRUE;
1.2513 + break;
1.2514 +
1.2515 + case -2:
1.2516 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2517 + freeFTYP(handle->ftyp);
1.2518 + handle->ftyp = NULL;
1.2519 + return MP4_ERROR;
1.2520 +
1.2521 + case -1:
1.2522 + default:
1.2523 + return MP4_ERROR;
1.2524 + }
1.2525 + }
1.2526 +
1.2527 + if (!handle->moov->trakAudio)
1.2528 + return MP4_ERROR;
1.2529 + if (!handle->moov->trakAudio->mdia)
1.2530 + return MP4_ERROR;
1.2531 + if (!(handle->type & MP4_TYPE_QCELP_13K))
1.2532 + return MP4_ERROR;
1.2533 +
1.2534 + if(handle->qcelpStoredAsMPEGAudio)
1.2535 + *qcelpStorageMode = 1;
1.2536 + else
1.2537 + *qcelpStorageMode = 0;
1.2538 +
1.2539 + return MP4_OK;
1.2540 +}
1.2541 +
1.2542 +extern EXPORT_C MP4Err MP4GetVideoFrameProperties(MP4Handle apihandle,mp4_u32 startindex,mp4_u32 sizeofarray,TFrameInfoParameters* aFrameInfoArray)
1.2543 +{
1.2544 +
1.2545 + mp4_u32 tmptime=0;
1.2546 + mp4_u32 sample=0;
1.2547 + mp4_u32 entry=0;
1.2548 + mp4_u32 videoSampleNumber = (startindex+sizeofarray)+1;
1.2549 + mp4_u32 i;
1.2550 + mp4_u32 j;
1.2551 + mp4_u32 index;
1.2552 + mp4_u32 actualIndex;
1.2553 +
1.2554 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2555 +
1.2556 + TBool sampleSyncTableExists = ETrue;
1.2557 + if (!handle->metaDataComplete)
1.2558 + {
1.2559 + switch (metaDataAvailable(handle))
1.2560 + {
1.2561 + case 0:
1.2562 + return MP4_NOT_AVAILABLE;
1.2563 + case 1:
1.2564 + handle->cafError = KErrNone;
1.2565 + if (readMetaData(handle) < 0)
1.2566 + {
1.2567 + // Reading of meta data failed, so free up any allocated memory
1.2568 + freeFTYP(handle->ftyp);
1.2569 + handle->ftyp = NULL;
1.2570 + freeMOOV(handle->moov);
1.2571 + handle->moov = NULL;
1.2572 +
1.2573 + if ( handle->cafError != KErrNone )
1.2574 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2575 + return handle->cafError;
1.2576 + }
1.2577 + else
1.2578 + {
1.2579 + return MP4_INVALID_INPUT_STREAM;
1.2580 + }
1.2581 + }
1.2582 + handle->metaDataComplete = MP4TRUE;
1.2583 + break;
1.2584 +
1.2585 + case -2:
1.2586 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2587 + freeFTYP(handle->ftyp);
1.2588 + handle->ftyp = NULL;
1.2589 + return MP4_ERROR;
1.2590 +
1.2591 + case -1:
1.2592 + default:
1.2593 + return MP4_ERROR;
1.2594 + }
1.2595 + }
1.2596 +
1.2597 +
1.2598 + if (!handle->moov)
1.2599 + return MP4_ERROR;
1.2600 +
1.2601 + if (handle->moov->trakVideo)
1.2602 + {
1.2603 + if (!handle->moov->trakVideo->mdia)
1.2604 + return MP4_ERROR;
1.2605 +
1.2606 + if (!handle->moov->trakVideo->mdia->minf)
1.2607 + return MP4_ERROR;
1.2608 +
1.2609 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2610 + return MP4_ERROR;
1.2611 +
1.2612 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsz) //for size
1.2613 + return MP4_ERROR;
1.2614 +
1.2615 + if (!handle->moov->trakVideo->mdia->minf->stbl->stss) //for type
1.2616 + {
1.2617 + // If sample sync table doesn't exist mark all frames as intra / random access point
1.2618 + sampleSyncTableExists = EFalse;
1.2619 + }
1.2620 +
1.2621 + if (!handle->moov->trakVideo->mdia->minf->stbl->stts) //For timeStamp
1.2622 + return MP4_ERROR;
1.2623 + }
1.2624 + else
1.2625 + {
1.2626 + return MP4_ERROR;
1.2627 + }
1.2628 +
1.2629 +
1.2630 + if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0) //For timeStamp
1.2631 + {
1.2632 + return MP4_ERROR;
1.2633 + }
1.2634 +
1.2635 + if((startindex+sizeofarray) > handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount) //more than number of frames
1.2636 + {
1.2637 + return MP4_ERROR;
1.2638 + }
1.2639 +
1.2640 + if(aFrameInfoArray == NULL)
1.2641 + {
1.2642 + return MP4_NO_OUTPUT_BUFFER;
1.2643 + }
1.2644 +
1.2645 + if ( sampleSyncTableExists )
1.2646 + {
1.2647 + for (i=0; i < handle->moov->trakVideo->mdia->minf->stbl->stss->entryCount; i++) //set all types to true
1.2648 + {
1.2649 + //because counting is stored from 1 but index from 0
1.2650 + mp4_u32 currFrame = handle->moov->trakVideo->mdia->minf->stbl->stss->sampleNumber[i] - 1;
1.2651 +
1.2652 + if ((currFrame >= startindex) && (currFrame < (startindex + sizeofarray)))
1.2653 + {
1.2654 + aFrameInfoArray[currFrame - startindex].iType = MP4TRUE;
1.2655 + }
1.2656 + }
1.2657 + }
1.2658 +
1.2659 + index=0; //initialize to beginning
1.2660 + actualIndex=0;//array indexer
1.2661 +
1.2662 + for(;;)
1.2663 + {
1.2664 + if(index< videoSampleNumber)
1.2665 + {
1.2666 + for(j=0;j<handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];j++)
1.2667 + {
1.2668 + if(index >=startindex)
1.2669 + {
1.2670 + //first initialize flag to false if not previously set to true.
1.2671 + if(aFrameInfoArray[actualIndex].iType != MP4TRUE)
1.2672 + {
1.2673 + aFrameInfoArray[actualIndex].iType = MP4FALSE;
1.2674 + }
1.2675 + //aFrameInfoArray[index].iStartTime = tmptime + handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry];
1.2676 + if(index==0) //so first frame of entire clip
1.2677 + {
1.2678 + aFrameInfoArray[actualIndex].iStartTime =0;
1.2679 + }
1.2680 + else
1.2681 + {
1.2682 + aFrameInfoArray[actualIndex].iStartTime = (mp4_u32)((mp4_double)tmptime * (mp4_double)1000 /
1.2683 + (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale + (mp4_double)0.5);
1.2684 + }
1.2685 + aFrameInfoArray[actualIndex].iSize = handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[index];
1.2686 + // If sample sync table doesn't exist mark all frames as intra / random access point
1.2687 + if (!sampleSyncTableExists)
1.2688 + {
1.2689 + aFrameInfoArray[actualIndex].iType = MP4TRUE;
1.2690 + }
1.2691 + actualIndex++; //point to next index in array
1.2692 + }
1.2693 + tmptime += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleDelta[entry];
1.2694 + //Now insert size before incrementing index
1.2695 + if(index == videoSampleNumber-2)
1.2696 + break;
1.2697 + index++;
1.2698 + }
1.2699 + if(index==videoSampleNumber-2)
1.2700 + break;
1.2701 + sample += handle->moov->trakVideo->mdia->minf->stbl->stts->sampleCount[entry];
1.2702 + entry++;
1.2703 + }
1.2704 + else
1.2705 + {
1.2706 + break;
1.2707 + }
1.2708 + }
1.2709 + return MP4_OK;
1.2710 +}
1.2711 +
1.2712 +extern EXPORT_C MP4Err MP4ParseGetVideoClipProperties(MP4Handle apihandle, TVideoClipProperties& aVideoClipProperties)
1.2713 +{
1.2714 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2715 + if (!handle)
1.2716 + {
1.2717 + return MP4_ERROR;
1.2718 + }
1.2719 +
1.2720 + if (!handle->metaDataComplete)
1.2721 + {
1.2722 + switch (metaDataAvailable(handle))
1.2723 + {
1.2724 + case 0:
1.2725 + return MP4_NOT_AVAILABLE;
1.2726 + case 1:
1.2727 + handle->cafError = KErrNone;
1.2728 + if (readMetaData(handle) < 0)
1.2729 + {
1.2730 + // Reading of meta data failed, so free up any allocated memory
1.2731 + freeFTYP(handle->ftyp);
1.2732 + handle->ftyp = NULL;
1.2733 + freeMOOV(handle->moov);
1.2734 + handle->moov = NULL;
1.2735 +
1.2736 + if ( handle->cafError != KErrNone )
1.2737 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2738 + return handle->cafError;
1.2739 + }
1.2740 + else
1.2741 + {
1.2742 + return MP4_INVALID_INPUT_STREAM;
1.2743 + }
1.2744 + }
1.2745 + handle->metaDataComplete = MP4TRUE;
1.2746 + break;
1.2747 +
1.2748 + case -2:
1.2749 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2750 + freeFTYP(handle->ftyp);
1.2751 + handle->ftyp = NULL;
1.2752 + return MP4_ERROR;
1.2753 +
1.2754 + case -1:
1.2755 + default:
1.2756 + return MP4_ERROR;
1.2757 + }
1.2758 + }
1.2759 +
1.2760 + if (!handle->moov)
1.2761 + return MP4_ERROR;
1.2762 + if (!handle->moov->trakVideo)
1.2763 + return MP4_ERROR;
1.2764 + if (!handle->moov->trakVideo->mdia)
1.2765 + return MP4_ERROR;
1.2766 + if (!handle->moov->trakVideo->mdia->minf)
1.2767 + return MP4_ERROR;
1.2768 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.2769 + return MP4_ERROR;
1.2770 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
1.2771 + return MP4_ERROR;
1.2772 +
1.2773 + /* Assume that the video type is the same for all sample entries. Just get the video type from the first one */
1.2774 + if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
1.2775 + {
1.2776 + if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263)
1.2777 + return MP4_ERROR;
1.2778 +
1.2779 + if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Level)
1.2780 + {
1.2781 + aVideoClipProperties.iH263Level = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Level;
1.2782 + return MP4_OK;
1.2783 + }
1.2784 + else
1.2785 + {
1.2786 + return MP4_ERROR;
1.2787 + }
1.2788 + }
1.2789 + else
1.2790 + {
1.2791 + return MP4_ERROR;
1.2792 + }
1.2793 +}
1.2794 +
1.2795 +extern EXPORT_C MP4Err MP4ParseGetUserDataAtom(MP4Handle apihandle,
1.2796 + mp4_u8& udtaLocation,
1.2797 + mp4_u32 udtaAtomType,
1.2798 + mp4_u8* buffer,
1.2799 + mp4_u32& bufferSize,
1.2800 + mp4_u32& atomIndex )
1.2801 + {
1.2802 + mp4_u32 size = 0;
1.2803 + mp4_u64 largesize = 0;
1.2804 + mp4_u32 type = 0;
1.2805 + mp4_i32 bytesread = 0;
1.2806 + mp4_i32 totalbytesread = 0;
1.2807 + MP4Err retError = MP4_OK;
1.2808 + userDataAtom* udta = NULL;
1.2809 + mp4_bool found = MP4FALSE;
1.2810 + mp4_u32 foundIndex = 0;
1.2811 +
1.2812 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.2813 +
1.2814 + if (!handle)
1.2815 + {
1.2816 + return MP4_ERROR;
1.2817 + }
1.2818 +
1.2819 + if (!handle->metaDataComplete)
1.2820 + {
1.2821 + switch (metaDataAvailable(handle))
1.2822 + {
1.2823 + case 0:
1.2824 + return MP4_NOT_AVAILABLE;
1.2825 + case 1:
1.2826 + handle->cafError = KErrNone;
1.2827 + if (readMetaData(handle) < 0)
1.2828 + {
1.2829 + // Reading of meta data failed, so free up any allocated memory
1.2830 + freeFTYP(handle->ftyp);
1.2831 + handle->ftyp = NULL;
1.2832 + freeMOOV(handle->moov);
1.2833 + handle->moov = NULL;
1.2834 +
1.2835 + if ( handle->cafError != KErrNone )
1.2836 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.2837 + return handle->cafError;
1.2838 + }
1.2839 + else
1.2840 + {
1.2841 + return MP4_INVALID_INPUT_STREAM;
1.2842 + }
1.2843 + }
1.2844 + handle->metaDataComplete = MP4TRUE;
1.2845 + break;
1.2846 +
1.2847 + case -2:
1.2848 + // Reading of FTYP meta data failed, so free up any allocated memory
1.2849 + freeFTYP(handle->ftyp);
1.2850 + handle->ftyp = NULL;
1.2851 + return MP4_ERROR;
1.2852 +
1.2853 + case -1:
1.2854 + default:
1.2855 + return MP4_ERROR;
1.2856 + }
1.2857 + }
1.2858 +
1.2859 + if (!handle->moov)
1.2860 + return MP4_ERROR;
1.2861 +
1.2862 + // Check where to read udta from.
1.2863 + switch ( udtaLocation )
1.2864 + {
1.2865 + case MP4_UDTA_NONE:
1.2866 + {
1.2867 + retError = MP4_UDTA_NOT_FOUND;
1.2868 + break;
1.2869 + }
1.2870 + case MP4_UDTA_MOOV:
1.2871 + {
1.2872 + if ( !handle->moov->udta )
1.2873 + {
1.2874 + retError = MP4_UDTA_NOT_FOUND;
1.2875 + break;
1.2876 + }
1.2877 + else
1.2878 + {
1.2879 + udta = handle->moov->udta;
1.2880 + }
1.2881 + break;
1.2882 + }
1.2883 + case MP4_UDTA_VIDEOTRAK:
1.2884 + {
1.2885 + if ( !handle->moov->trakVideo )
1.2886 + {
1.2887 + retError = MP4_UDTA_NOT_FOUND;
1.2888 + break;
1.2889 + }
1.2890 + if ( !handle->moov->trakVideo->udta )
1.2891 + {
1.2892 + retError = MP4_UDTA_NOT_FOUND;
1.2893 + }
1.2894 + else
1.2895 + {
1.2896 + udta = handle->moov->trakVideo->udta;
1.2897 + }
1.2898 + break;
1.2899 + }
1.2900 + case MP4_UDTA_AUDIOTRAK:
1.2901 + {
1.2902 + if (!handle->moov->trakAudio)
1.2903 + {
1.2904 + retError = MP4_UDTA_NOT_FOUND;
1.2905 + break;
1.2906 + }
1.2907 + if ( !handle->moov->trakAudio->udta )
1.2908 + {
1.2909 + retError = MP4_UDTA_NOT_FOUND;
1.2910 + }
1.2911 + else
1.2912 + {
1.2913 + udta = handle->moov->trakAudio->udta;
1.2914 + }
1.2915 + break;
1.2916 + }
1.2917 + default:
1.2918 + {
1.2919 + retError = MP4_INVALID_TYPE;
1.2920 + }
1.2921 + }
1.2922 +
1.2923 + if ( retError == MP4_OK ) // valid UDTA found.
1.2924 + {
1.2925 + if ( !udta->atomhdr )
1.2926 + {
1.2927 + retError = MP4_UDTA_NOT_FOUND;
1.2928 + }
1.2929 + if ( !udta->atomcontentloc || (udta->atomcontentsize == 0) )
1.2930 + {
1.2931 + retError = MP4_UDTA_NOT_FOUND;
1.2932 + }
1.2933 +
1.2934 + // seek to UDTA atom in memory structure or file.
1.2935 + if (handle->file) /* Input is in a file */
1.2936 + {
1.2937 + if (seekFileAbs(handle, udta->atomcontentloc) != 0)
1.2938 + return MP4_CANT_SEEK;
1.2939 + }
1.2940 + else
1.2941 + {
1.2942 + handle->absPosition = udta->atomcontentloc;
1.2943 + }
1.2944 +
1.2945 + // search for wanted atom from UDTA and read it to buffer
1.2946 + while ( totalbytesread < (mp4_i32)udta->atomcontentsize )
1.2947 + {
1.2948 + if (peekData(handle, handle->buf, 16) < 0)
1.2949 + return MP4_ERROR;
1.2950 +
1.2951 + size = u32endian(*((mp4_u32 *)handle->buf));
1.2952 + type = u32endian(*((mp4_u32 *)(handle->buf+4)));
1.2953 +
1.2954 + if ( type == udtaAtomType )
1.2955 + {
1.2956 + if ( atomIndex == foundIndex )
1.2957 + {
1.2958 + if ( size == 1 )
1.2959 + {
1.2960 + largesize = u64endian(*((mp4_u64*)(handle->buf+8)));
1.2961 + size = (mp4_u32)I64INT(largesize);
1.2962 + }
1.2963 + if ( size > bufferSize )
1.2964 + {
1.2965 + // Although the output buffer supplied by the caller is
1.2966 + // not large enough to store the sub user atom's content, keep
1.2967 + // parsing thru the whole user data to retrieve the highest index
1.2968 + // to be returned thru the atomIndex parameter
1.2969 + bufferSize = size;
1.2970 + retError = MP4_OUTPUT_BUFFER_TOO_SMALL;
1.2971 + bytesread = readUnknown(handle);
1.2972 + if (bytesread < 0)
1.2973 + return MP4_ERROR;
1.2974 + }
1.2975 + else
1.2976 + {
1.2977 + bytesread = readData(handle, buffer, size);
1.2978 + if (bytesread < 0)
1.2979 + return MP4_ERROR;
1.2980 + bufferSize = bytesread;
1.2981 + }
1.2982 +
1.2983 + totalbytesread += bytesread;
1.2984 + foundIndex += 1;
1.2985 + found = MP4TRUE;
1.2986 + }
1.2987 + else
1.2988 + {
1.2989 + bytesread = readUnknown(handle);
1.2990 + if (bytesread < 0)
1.2991 + return MP4_ERROR;
1.2992 + totalbytesread += bytesread;
1.2993 + foundIndex += 1;
1.2994 + }
1.2995 + }
1.2996 + else
1.2997 + {
1.2998 + bytesread = readUnknown(handle);
1.2999 + if (bytesread < 0)
1.3000 + return MP4_ERROR;
1.3001 + totalbytesread += bytesread;
1.3002 + }
1.3003 + }
1.3004 + }
1.3005 +
1.3006 + if ( ( atomIndex > foundIndex ) || !found )
1.3007 + {
1.3008 + retError = MP4_UDTA_NOT_FOUND;
1.3009 + }
1.3010 +
1.3011 + // fill how many wanted type atom there is in asked UDTA.
1.3012 + if ( found )
1.3013 + {
1.3014 + atomIndex = foundIndex - 1;
1.3015 + }
1.3016 + else
1.3017 + {
1.3018 + atomIndex = 0;
1.3019 + }
1.3020 +
1.3021 + // fill udtaLocation
1.3022 + udtaLocation = MP4_UDTA_NONE;
1.3023 +
1.3024 + if ( handle->moov->udta )
1.3025 + {
1.3026 + udtaLocation |= MP4_UDTA_MOOV;
1.3027 + }
1.3028 + if ( handle->moov->trakVideo )
1.3029 + {
1.3030 + if ( handle->moov->trakVideo->udta )
1.3031 + {
1.3032 + udtaLocation |= MP4_UDTA_VIDEOTRAK;
1.3033 + }
1.3034 + }
1.3035 + if ( handle->moov->trakAudio )
1.3036 + {
1.3037 + if ( handle->moov->trakAudio->udta )
1.3038 + {
1.3039 + udtaLocation |= MP4_UDTA_AUDIOTRAK;
1.3040 + }
1.3041 + }
1.3042 +
1.3043 + return retError;
1.3044 + }
1.3045 +
1.3046 +extern EXPORT_C MP4Err MP4ParseNextVideoFrameDependencies(MP4Handle apihandle, mp4_u8* aDependsOn, mp4_u8* aIsDependentOn, mp4_u8* aHasRedundancy)
1.3047 +{
1.3048 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.3049 + mp4_u32 type = 0;
1.3050 +
1.3051 + if (!handle)
1.3052 + {
1.3053 + return MP4_ERROR;
1.3054 + }
1.3055 + if(!aDependsOn || !aIsDependentOn || !aHasRedundancy)
1.3056 + {
1.3057 + return MP4_NO_OUTPUT_BUFFER;
1.3058 + }
1.3059 + if (!handle->metaDataComplete)
1.3060 + {
1.3061 + switch (metaDataAvailable(handle))
1.3062 + {
1.3063 + case 0:
1.3064 + return MP4_NOT_AVAILABLE;
1.3065 +
1.3066 + case 1:
1.3067 + if (readMetaData(handle) < 0)
1.3068 + {
1.3069 + // Reading of meta data failed, so free up any allocated memory
1.3070 + freeFTYP(handle->ftyp);
1.3071 + handle->ftyp = NULL;
1.3072 + freeMOOV(handle->moov);
1.3073 + handle->moov = NULL;
1.3074 +
1.3075 + return MP4_INVALID_INPUT_STREAM;
1.3076 + }
1.3077 +
1.3078 + handle->metaDataComplete = MP4TRUE;
1.3079 + break;
1.3080 +
1.3081 + case -2:
1.3082 + // Reading of FTYP meta data failed, so free up any allocated memory
1.3083 + freeFTYP(handle->ftyp);
1.3084 + handle->ftyp = NULL;
1.3085 + return MP4_ERROR;
1.3086 +
1.3087 + case -1:
1.3088 + default:
1.3089 + return MP4_ERROR;
1.3090 + }
1.3091 + }
1.3092 +
1.3093 + if (determineVideoType(handle, &type) < 0)
1.3094 + {
1.3095 + return MP4_ERROR;
1.3096 + }
1.3097 + if( !isAvcVideo(type) )
1.3098 + {
1.3099 + *aDependsOn = 0; // Unknown
1.3100 + *aIsDependentOn = 0; // Unknown
1.3101 + *aHasRedundancy = 0; // Unknown
1.3102 + return MP4_OK;
1.3103 + }
1.3104 +
1.3105 + if (!handle->moov)
1.3106 + return MP4_ERROR;
1.3107 + if (!handle->moov->trakVideo)
1.3108 + return MP4_ERROR;
1.3109 + if (!handle->moov->trakVideo->mdia)
1.3110 + return MP4_ERROR;
1.3111 + if (!handle->moov->trakVideo->mdia->minf)
1.3112 + return MP4_ERROR;
1.3113 + if (!handle->moov->trakVideo->mdia->minf->stbl)
1.3114 + return MP4_ERROR;
1.3115 + if (!handle->moov->trakVideo->mdia->minf->stbl->sdtp)
1.3116 + {
1.3117 + *aDependsOn = 0; // Unknown
1.3118 + *aIsDependentOn = 0; // Unknown
1.3119 + *aHasRedundancy = 0; // Unknown
1.3120 + return MP4_OK;
1.3121 + }
1.3122 + if (!handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep)
1.3123 + {
1.3124 + return MP4_ERROR;
1.3125 + }
1.3126 +
1.3127 + if (handle->videoSampleNum <= 0)
1.3128 + {
1.3129 + return MP4_ERROR;
1.3130 + }
1.3131 +
1.3132 + if(handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sDependsOn > 2 ||
1.3133 + handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sIsDependentOn > 2 ||
1.3134 + handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sHasRedundancy > 2)
1.3135 + {
1.3136 + return MP4_ERROR;
1.3137 + }
1.3138 + *aDependsOn = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sDependsOn;
1.3139 + *aIsDependentOn = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sIsDependentOn;
1.3140 + *aHasRedundancy = handle->moov->trakVideo->mdia->minf->stbl->sdtp->dep[handle->videoSampleNum - 1].sHasRedundancy;
1.3141 + return MP4_OK;
1.3142 +}
1.3143 +
1.3144 +extern EXPORT_C MP4Err MP4ParseReadAudioFramesAsync(MP4Handle apihandle, M3GPMP4LibAsyncObserver* aObserver, mp4_u8 *buffer, mp4_u32* buffersize)
1.3145 +{
1.3146 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.3147 +
1.3148 + if (!handle->file)
1.3149 + {
1.3150 + // async operation is only supported for files.
1.3151 + return MP4_FILE_ERROR;
1.3152 + }
1.3153 +
1.3154 + if (!handle->metaDataComplete)
1.3155 + {
1.3156 + switch (metaDataAvailable(handle))
1.3157 + {
1.3158 + case 0:
1.3159 + return MP4_NOT_AVAILABLE;
1.3160 + case 1:
1.3161 + handle->cafError = KErrNone;
1.3162 + if (readMetaData(handle) < 0)
1.3163 + {
1.3164 + // Reading of meta data failed, so free up any allocated memory
1.3165 + freeFTYP(handle->ftyp);
1.3166 + handle->ftyp = NULL;
1.3167 + freeMOOV(handle->moov);
1.3168 + handle->moov = NULL;
1.3169 +
1.3170 + if ( handle->cafError != KErrNone )
1.3171 + {
1.3172 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.3173 + return handle->cafError;
1.3174 + }
1.3175 + else
1.3176 + {
1.3177 + return MP4_INVALID_INPUT_STREAM;
1.3178 + }
1.3179 + }
1.3180 + handle->metaDataComplete = MP4TRUE;
1.3181 + break;
1.3182 +
1.3183 + case -2:
1.3184 + // Reading of FTYP meta data failed, so free up any allocated memory
1.3185 + freeFTYP(handle->ftyp);
1.3186 + handle->ftyp = NULL;
1.3187 + return MP4_ERROR;
1.3188 +
1.3189 + case -1:
1.3190 + default:
1.3191 + return MP4_ERROR;
1.3192 + }
1.3193 + }
1.3194 +
1.3195 + handle->asyncObserver = aObserver;
1.3196 +
1.3197 + /* Is audio available? */
1.3198 + if (!((handle->type & MP4_TYPE_MPEG4_AUDIO) ||
1.3199 + (handle->type & MP4_TYPE_AMR_NB) ||
1.3200 + (handle->type & MP4_TYPE_AMR_WB) ||
1.3201 + (handle->type & MP4_TYPE_QCELP_13K)))
1.3202 + return MP4_ERROR;
1.3203 +
1.3204 + /* Are there samples left? */
1.3205 + if (handle->audioLast)
1.3206 + return MP4_NO_FRAME;
1.3207 +
1.3208 + if (!handle->moov)
1.3209 + return MP4_ERROR;
1.3210 + if (!handle->moov->trakAudio)
1.3211 + return MP4_ERROR;
1.3212 +
1.3213 + switch (fetchAudioSampleAsync(handle, handle->moov->trakAudio, buffer, buffersize))
1.3214 + {
1.3215 + case -1:
1.3216 + return MP4_ERROR;
1.3217 + case -2:
1.3218 + return MP4_BUFFER_TOO_SMALL;
1.3219 + case -4:
1.3220 + return MP4_INVALID_INPUT_STREAM;
1.3221 + case MP4_OUT_OF_MEMORY:
1.3222 + return MP4_OUT_OF_MEMORY;
1.3223 + default:
1.3224 + break;
1.3225 + }
1.3226 + return MP4_OK;
1.3227 +}
1.3228 +
1.3229 +extern EXPORT_C MP4Err MP4ParseReadVideoFrameAsync(MP4Handle apihandle,
1.3230 + M3GPMP4LibAsyncObserver* aObserver,
1.3231 + mp4_u8* buffer,
1.3232 + mp4_u32* buffersize)
1.3233 +{
1.3234 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.3235 +
1.3236 + if (!handle->file)
1.3237 + {
1.3238 + // async operation is only supported for files.
1.3239 + return MP4_FILE_ERROR;
1.3240 + }
1.3241 +
1.3242 + if (!handle->metaDataComplete)
1.3243 + {
1.3244 + switch (metaDataAvailable(handle))
1.3245 + {
1.3246 + case 0:
1.3247 +
1.3248 + return MP4_NOT_AVAILABLE;
1.3249 +
1.3250 + case 1:
1.3251 + handle->cafError = KErrNone;
1.3252 + if (readMetaData(handle) < 0)
1.3253 + {
1.3254 + // Reading of meta data failed, so free up any allocated memory
1.3255 + freeFTYP(handle->ftyp);
1.3256 + handle->ftyp = NULL;
1.3257 + freeMOOV(handle->moov);
1.3258 + handle->moov = NULL;
1.3259 +
1.3260 + if ( handle->cafError != KErrNone )
1.3261 + {
1.3262 + // if CAF/DRM caused the error return it instead of generic errorcode.
1.3263 + return handle->cafError;
1.3264 + }
1.3265 + else
1.3266 + {
1.3267 + return MP4_INVALID_INPUT_STREAM;
1.3268 + }
1.3269 + }
1.3270 + handle->metaDataComplete = MP4TRUE;
1.3271 + break;
1.3272 +
1.3273 + case -2:
1.3274 + // Reading of FTYP meta data failed, so free up any allocated memory
1.3275 + freeFTYP(handle->ftyp);
1.3276 + handle->ftyp = NULL;
1.3277 + return MP4_ERROR;
1.3278 +
1.3279 + case -1:
1.3280 + default:
1.3281 + return MP4_ERROR;
1.3282 + }
1.3283 + }
1.3284 +
1.3285 + /* Is video available? */
1.3286 + if (!((handle->type & MP4_TYPE_MPEG4_VIDEO) ||
1.3287 + (handle->type & MP4_TYPE_H263_PROFILE_0) ||
1.3288 + (handle->type & MP4_TYPE_H263_PROFILE_3) ||
1.3289 + containsAvcVideo( handle->type ) ))
1.3290 + return MP4_ERROR;
1.3291 +
1.3292 + /* Are there samples left? */
1.3293 + if (handle->videoLast)
1.3294 + return MP4_NO_FRAME;
1.3295 +
1.3296 + handle->asyncObserver = aObserver;
1.3297 +
1.3298 + if (!handle->moov)
1.3299 + return MP4_ERROR;
1.3300 + if (!handle->moov->trakVideo)
1.3301 + return MP4_ERROR;
1.3302 +
1.3303 + switch (fetchVideoFrameAsync(handle, handle->moov->trakVideo, buffer, buffersize ))
1.3304 + {
1.3305 + case -1:
1.3306 + return MP4_ERROR;
1.3307 + case -2:
1.3308 + return MP4_BUFFER_TOO_SMALL;
1.3309 + case -3:
1.3310 + return MP4_NOT_AVAILABLE;
1.3311 + case -4:
1.3312 + return MP4_INVALID_INPUT_STREAM;
1.3313 + case MP4_OUT_OF_MEMORY:
1.3314 + return MP4_OUT_OF_MEMORY;
1.3315 + default:
1.3316 + break;
1.3317 + }
1.3318 +
1.3319 + return MP4_OK;
1.3320 +}
1.3321 +
1.3322 +extern EXPORT_C void MP4CancelReadFrame(MP4Handle ahandle)
1.3323 + {
1.3324 + MP4HandleImp handle = (MP4HandleImp)ahandle;
1.3325 +
1.3326 + if (handle->asyncReader)
1.3327 + {
1.3328 + handle->asyncReader->Cancel();
1.3329 + }
1.3330 + }
1.3331 +
1.3332 +extern EXPORT_C MP4Err MP4ParseGetID32Location(MP4Handle apihandle, mp4_u32& location)
1.3333 + {
1.3334 + MP4HandleImp handle = (MP4HandleImp)apihandle;
1.3335 +
1.3336 + if (!handle)
1.3337 + {
1.3338 + return MP4_ERROR;
1.3339 + }
1.3340 +
1.3341 + if (!handle->metaDataComplete)
1.3342 + {
1.3343 + switch (metaDataAvailable(handle))
1.3344 + {
1.3345 + case 0:
1.3346 + return MP4_NOT_AVAILABLE;
1.3347 + case 1:
1.3348 + handle->cafError = KErrNone;
1.3349 + if (readMetaData(handle) < 0)
1.3350 + {
1.3351 + // Reading of meta data failed, so free up any allocated memory
1.3352 + freeFTYP(handle->ftyp);
1.3353 + handle->ftyp = NULL;
1.3354 + freeMOOV(handle->moov);
1.3355 + handle->moov = NULL;
1.3356 + if (handle->cafError != KErrNone)
1.3357 + {// if CAF/DRM caused the error return it instead of generic errorcode.
1.3358 + return handle->cafError;
1.3359 + }
1.3360 + else
1.3361 + {
1.3362 + return MP4_INVALID_INPUT_STREAM;
1.3363 + }
1.3364 + }
1.3365 + handle->metaDataComplete = MP4TRUE;
1.3366 + break;
1.3367 +
1.3368 + case -2:
1.3369 + // Reading of FTYP meta data failed, so free up any allocated memory
1.3370 + freeFTYP(handle->ftyp);
1.3371 + handle->ftyp = NULL;
1.3372 + return MP4_ERROR;
1.3373 +
1.3374 + case -1:
1.3375 + default:
1.3376 + return MP4_ERROR;
1.3377 + }
1.3378 + }
1.3379 +
1.3380 + if (!handle->moov)
1.3381 + return MP4_ERROR;
1.3382 +
1.3383 + metaAtom* meta = handle->moov->meta;
1.3384 + if (!meta)
1.3385 + return MP4_NOT_AVAILABLE;
1.3386 +
1.3387 + if (!meta->atomhdr)
1.3388 + return MP4_NOT_AVAILABLE;
1.3389 +
1.3390 + if(meta->ID32)
1.3391 + {
1.3392 + location = meta->ID32->atomcontentloc;
1.3393 + }
1.3394 + else
1.3395 + {
1.3396 + return MP4_NOT_AVAILABLE;
1.3397 + }
1.3398 +
1.3399 + return MP4_OK;
1.3400 + }
1.3401 +// End of File