/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "../includes/common.h" // This PoC is only for 64-bit builds #if _64_BIT #include #define DEQUEUE_BUFFER_TIMEOUT_MICROSECONDS 1000 #define TOTAL_TIMEOUT_MICROSECONDS (300 * 1000 * 1000) #define FILE_SIZE 72 #define VIDEO_MAX_WIDTH 176 #define VIDEO_MAX_HEIGHT 144 #endif /* _64_BIT */ int main(int argc, char *argv[]) { (void)argc; (void)argv; // This PoC is only for 64-bit builds #if _64_BIT if (argc != 2) { return EXIT_FAILURE; } FILE *inFile = fopen(argv[1], "rb"); if (!inFile) { return EXIT_FAILURE; } AMediaCodec *codec; media_status_t status; int64_t inActiveTime = 0ll; bool isEncoder = false; codec = AMediaCodec_createCodecByName("c2.android.av1-aom.decoder"); if (!codec) { fclose(inFile); return EXIT_FAILURE; } /* Set Format */ AMediaFormat *format = AMediaFormat_new(); if (!format) { fclose(inFile); AMediaCodec_delete(codec); return EXIT_FAILURE; } AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, "video/av01"); AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, FILE_SIZE); AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, VIDEO_MAX_WIDTH); AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, VIDEO_MAX_HEIGHT); AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder); AMediaCodec_start(codec); size_t filePos = 0; bool inputEOS = false; while (inActiveTime < TOTAL_TIMEOUT_MICROSECONDS) { /* Queue input data */ if (!inputEOS) { uint32_t bufferFlags = 0; ssize_t inIdx = AMediaCodec_dequeueInputBuffer(codec, DEQUEUE_BUFFER_TIMEOUT_MICROSECONDS); if (inIdx >= 0) { ssize_t bytesRead = 0; size_t bufSize; uint8_t *buf = AMediaCodec_getInputBuffer(codec, inIdx, &bufSize); if (filePos < FILE_SIZE) { bytesRead = fread(buf, 1, FILE_SIZE, inFile); filePos += FILE_SIZE; fseek(inFile, filePos, SEEK_SET); } if (bytesRead <= 0) { bytesRead = 0; inputEOS = true; bufferFlags |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM; } status = AMediaCodec_queueInputBuffer(codec, inIdx, 0, bytesRead, 0, bufferFlags); if (status != AMEDIA_OK) { break; } inActiveTime = 0; } else if (inIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { inActiveTime += DEQUEUE_BUFFER_TIMEOUT_MICROSECONDS; } else { break; } } /* Dequeue output */ AMediaCodecBufferInfo info; ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(codec, &info, DEQUEUE_BUFFER_TIMEOUT_MICROSECONDS); if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED || outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) { inActiveTime = 0; } else if (outIdx >= 0) { status = AMediaCodec_releaseOutputBuffer(codec, outIdx, false); if (status != AMEDIA_OK) { break; } if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { break; } inActiveTime = 0; } else if (outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { inActiveTime += DEQUEUE_BUFFER_TIMEOUT_MICROSECONDS; } else { break; } } AMediaFormat_delete(format); AMediaCodec_stop(codec); AMediaCodec_delete(codec); fclose(inFile); #endif /* _64_BIT */ return EXIT_SUCCESS; }