/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is MPEG4IP.
 * 
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 * Portions created by Cisco Systems Inc. are
 * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
 * 
 * Contributor(s): 
 *        Dave Mackie        dmackie@cisco.com
 */

#include <mp4v2/mp4v2.h>
#include <malloc.h>

main(int argc, char** argv)
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
        return 1;
    }

    MP4LogSetLevel(MP4_LOG_VERBOSE4);

    char* fileName = argv[1];

    // open the mp4 file, and read meta-info
    MP4FileHandle mp4File = MP4Read(fileName);

    uint8_t profileLevel = MP4GetVideoProfileLevel(mp4File);

    // get a handle on the first video track
    MP4TrackId trackId = MP4FindTrackId(mp4File, 0, "video");

    // gather the crucial track information 

    uint32_t timeScale = MP4GetTrackTimeScale(mp4File, trackId);

    // note all times and durations 
    // are in units of the track time scale

    MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId);

    MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId);

    uint32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, trackId);

    uint8_t* pConfig;
    uint32_t configSize = 0;

    MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize);

    // initialize decoder with Elementary Stream (ES) configuration

    // done with our copy of ES configuration
    MP4Free(pConfig);

    // now consecutively read and display the track samples

    uint8_t* pSample = (uint8_t*)malloc(maxSampleSize);
    uint32_t sampleSize;
    MP4Timestamp sampleTime;
    MP4Duration sampleDuration;
    MP4Duration sampleRenderingOffset;
    bool isSyncSample;

    for (MP4SampleId sampleId = 1; sampleId <= numSamples; sampleId++) {

        // give ReadSample our own buffer, and let it know how big it is
        sampleSize = maxSampleSize;

        // read next sample from video track
        MP4ReadSample(mp4File, trackId, sampleId, 
            &pSample, &sampleSize,
            &sampleTime, &sampleDuration, &sampleRenderingOffset, 
            &isSyncSample);

        // convert timestamp and duration from track time to milliseconds
        uint64_t myTime = MP4ConvertFromTrackTimestamp(mp4File, trackId, 
            sampleTime, MP4_MSECS_TIME_SCALE);

        uint64_t myDuration = MP4ConvertFromTrackDuration(mp4File, trackId,
            sampleDuration, MP4_MSECS_TIME_SCALE);

        // decode frame and display it
    }

    MP4Free(pSample);

    // close mp4 file
    MP4Close(mp4File);

    // Note to seek to time 'when' in the track
    // use MP4GetSampleIdFromTime(MP4FileHandle hFile, 
    //        MP4Timestamp when, bool wantSyncSample)
    // 'wantSyncSample' determines if a sync sample is desired or not
    // e.g.
    // MP4Timestamp when = 
    //    MP4ConvertToTrackTimestamp(mp4File, trackId, 30, MP4_SECS_TIME_SCALE);
    // MP4SampleId newSampleId = MP4GetSampleIdFromTime(mp4File, when, true);
    // MP4ReadSample(mp4File, trackId, newSampleId, ...);
    // 
    // Note that start time for sample may be later than 'when'

    return 0;
}

