1044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat/*
2044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * Copyright (C) 2014 The Android Open Source Project
3044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * All rights reserved.
4044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat *
5044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * Redistribution and use in source and binary forms, with or without
6044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * modification, are permitted provided that the following conditions
7044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * are met:
8044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * * Redistributions of source code must retain the above copyright
9044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * notice, this list of conditions and the following disclaimer.
10044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * * Redistributions in binary form must reproduce the above copyright
11044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * notice, this list of conditions and the following disclaimer in
12044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * the documentation and/or other materials provided with the
13044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * distribution.
14044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat *
15044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat * SUCH DAMAGE.
27044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat */
28044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
29044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat#include <stdio.h>
30044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat#include <stdint.h>
31044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat#include <assert.h>
32044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat#include <stdlib.h>
33044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
34044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat#include "mp4enc_api.h"
35044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
36044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat// Constants.
37044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhatenum {
38044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kMaxWidth         = 720,
39044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kMaxHeight        = 480,
40044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kMaxFrameRate     = 30,
41044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kMaxBitrate       = 2048, // in kbps.
42044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kOutputBufferSize = 250 * 1024,
43044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    kIDRFrameRefreshIntervalInSec = 1, // in seconds.
44044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat};
45044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
46044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhatint main(int argc, char *argv[]) {
47044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
48044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (argc < 8) {
49044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Usage %s <input yuv> <output file> <mode> <width> "
50044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat                        "<height> <frame rate> <bitrate in kbps>\n", argv[0]);
51044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "mode : h263 or mpeg4\n");
52044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Max width %d\n", kMaxWidth);
53044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Max height %d\n", kMaxHeight);
54044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Max framerate %d\n", kMaxFrameRate);
55044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Max bitrate %d kbps\n", kMaxBitrate);
56044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
57044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
58044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
59044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Read mode.
60044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    bool isH263mode;
61044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (strcmp(argv[3], "mpeg4") == 0) {
62044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        isH263mode = false;
63044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    } else if (strcmp(argv[3], "h263") == 0) {
64044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        isH263mode = true;
65044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    } else {
66044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Unsupported mode %s\n", argv[3]);
67044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
68044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
69044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
70044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Read height and width.
71044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t width;
72044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t height;
73044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    width = atoi(argv[4]);
74044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    height = atoi(argv[5]);
75044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (width > kMaxWidth || height > kMaxHeight || width <= 0 || height <= 0) {
76044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Unsupported dimensions %dx%d\n", width, height);
77044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
78044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
79044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
80044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (width % 16 != 0 || height % 16 != 0) {
81044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Video frame size %dx%d must be a multiple of 16\n",
82044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            width, height);
83044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
84044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
85044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
86044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Read frame rate.
87044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t frameRate;
88044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    frameRate = atoi(argv[6]);
89044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (frameRate > kMaxFrameRate || frameRate <= 0) {
90044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Unsupported frame rate %d\n", frameRate);
91044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
92044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
93044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
94044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Read bitrate.
95044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t bitrate;
96044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    bitrate = atoi(argv[7]);
97044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (bitrate > kMaxBitrate || bitrate <= 0) {
98044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Unsupported bitrate %d\n", bitrate);
99044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
100044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
101044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
102044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Allocate input buffer.
103044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    uint8_t *inputBuf = (uint8_t *)malloc((width * height * 3) / 2);
104044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    assert(inputBuf != NULL);
105044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
106044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Allocate output buffer.
107044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    uint8_t *outputBuf = (uint8_t *)malloc(kOutputBufferSize);
108044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    assert(outputBuf != NULL);
109044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
110044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Open the input file.
111044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    FILE *fpInput = fopen(argv[1], "rb");
112044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (fpInput == NULL) {
113044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Could not open %s\n", argv[1]);
114044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(inputBuf);
115044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(outputBuf);
116044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
117044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
118044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
119044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Open the output file.
120044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    FILE *fpOutput = fopen(argv[2], "wb");
121044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (fpOutput == NULL) {
122044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Could not open %s\n", argv[2]);
123044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(inputBuf);
124044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(outputBuf);
125044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fclose(fpInput);
126044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
127044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
128044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
129044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Initialize the encoder parameters.
130044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    tagvideoEncOptions encParams;
131044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    memset(&encParams, 0, sizeof(tagvideoEncOptions));
132044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (!PVGetDefaultEncOption(&encParams, 0)) {
133044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Failed to get default encoding parameters\n");
134044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(inputBuf);
135044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        free(outputBuf);
136044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fclose(fpInput);
137044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fclose(fpOutput);
138044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
139044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
140044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
141044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (isH263mode == false) {
142044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        encParams.encMode = COMBINE_MODE_WITH_ERR_RES;
143044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    } else {
144044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        encParams.encMode = H263_MODE;
145044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
146044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.encWidth[0] = width;
147044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.encHeight[0] = height;
148044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.encFrameRate[0] = frameRate;
149044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.rcType = VBR_1;
150044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.vbvDelay = 5.0f;
151044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.profile_level = CORE_PROFILE_LEVEL2;
152044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.packetSize = 32;
153044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.rvlcEnable = PV_OFF;
154044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.numLayers = 1;
155044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.timeIncRes = 1000;
156044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.tickPerSrc = encParams.timeIncRes / frameRate;
157044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
158044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.bitRate[0] = bitrate * 1024;
159044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.iQuant[0] = 15;
160044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.pQuant[0] = 12;
161044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.quantType[0] = 0;
162044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.noFrameSkipped = PV_OFF;
163044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
164044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t  IDRFrameRefreshIntervalInSec = kIDRFrameRefreshIntervalInSec;
165044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (IDRFrameRefreshIntervalInSec == 0) {
166044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        encParams.intraPeriod = 1;  // All I frames.
167044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    } else {
168044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        encParams.intraPeriod = (IDRFrameRefreshIntervalInSec * frameRate);
169044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
170044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
171044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.numIntraMB = 0;
172044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.sceneDetect = PV_ON;
173044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.searchRange = 16;
174044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.mv8x8Enable = PV_OFF;
175044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.gobHeaderInterval = 0;
176044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.useACPred = PV_ON;
177044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    encParams.intraDCVlcTh = 0;
178044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
179044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Initialize the handle.
180044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    tagvideoEncControls handle;
181044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    memset(&handle, 0, sizeof(tagvideoEncControls));
182044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
183044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Initialize the encoder.
184044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (!PVInitVideoEncoder(&handle, &encParams)) {
185044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Failed to initialize the encoder\n");
186044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
187044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
188044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
189044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Generate the header.
190044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t headerLength = kOutputBufferSize;
191044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    if (!PVGetVolHeader(&handle, outputBuf, &headerLength, 0)) {
192044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fprintf(stderr, "Failed to get VOL header\n");
193044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        return EXIT_FAILURE;
194044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
195044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    fwrite(outputBuf, 1, headerLength, fpOutput);
196044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
197044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Core loop.
198044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t retVal = EXIT_SUCCESS;
199044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t frameSize = (width * height * 3) / 2;
200044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    int32_t numFramesEncoded = 0;
201044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
202044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    while (1) {
203044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        // Read the input frame.
204044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        int32_t bytesRead;
205044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        bytesRead = fread(inputBuf, 1, frameSize, fpInput);
206044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        if (bytesRead != frameSize) {
207044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            break; // End of file.
208044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        }
209044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
210044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        // Encode the input frame.
211044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        VideoEncFrameIO vin, vout;
212044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        memset(&vin, 0, sizeof(vin));
213044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        memset(&vout, 0, sizeof(vout));
214044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.height = height; // height is multiple of 16.
215044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.pitch = width; // width is multiple of 16.
216044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.timestamp = (numFramesEncoded * 1000) / frameRate;  // in ms.
217044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.yChan = inputBuf;
218044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.uChan = vin.yChan + vin.height * vin.pitch;
219044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
220044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
221044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        uint32_t modTimeMs = 0;
222044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        int32_t nLayer = 0;
223044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        MP4HintTrack hintTrack;
224044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        int32_t dataLength = kOutputBufferSize;
225044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        if (!PVEncodeVideoFrame(&handle, &vin, &vout,
226044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat                &modTimeMs, outputBuf, &dataLength, &nLayer) ||
227044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            !PVGetHintTrack(&handle, &hintTrack)) {
228044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            fprintf(stderr, "Failed to encode frame or get hink track at "
229044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat                    " frame %d\n", numFramesEncoded);
230044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            retVal = EXIT_FAILURE;
231044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat            break;
232044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        }
233044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        PVGetOverrunBuffer(&handle);
234044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        numFramesEncoded++;
235044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
236044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        // Write the output.
237044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat        fwrite(outputBuf, 1, dataLength, fpOutput);
238044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    }
239044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
240044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Close input and output file.
241044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    fclose(fpInput);
242044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    fclose(fpOutput);
243044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
244044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Free allocated memory.
245044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    free(inputBuf);
246044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    free(outputBuf);
247044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat
248044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    // Close encoder instance.
249044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    PVCleanUpVideoEncoder(&handle);
250044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat    return retVal;
251044c6ae441f14102551c1ba918d02d5c8d12c21eAshok Bhat}
252