| /* |
| * 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 <stdlib.h> |
| #include "../includes/common.h" |
| |
| // This PoC is only for 64-bit builds |
| #if _64_BIT |
| #include <media/NdkMediaCodec.h> |
| |
| #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.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; |
| } |