blob: 4f1bd552dfef1a58aa6979f25b60aef4b6714b7e [file] [log] [blame]
/**
* Copyright (C) 2019 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.
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <stdlib.h>
#include "ihevc_typedefs.h"
#include "ihevcd_cxa.h"
#define TOTAL_BUF_LEN (1280 * 720 * 3 / 2)
#define BUF_LEN_0 (1280 * 720)
#define BUF_LEN_1 (1280 * 720 / 2)
FILE *ps_ip_file = NULL;
UWORD8 *pu1_bs_buf = NULL;
ivd_out_bufdesc_t *ps_out_buf = NULL;
#define EXIT_ON_ERROR(status) \
{\
if (IV_SUCCESS != status) {\
if(ps_ip_file)\
fclose(ps_ip_file);\
\
if(ps_out_buf) { \
if(ps_out_buf->pu1_bufs[0]) {\
free(ps_out_buf->pu1_bufs[0]);\
}\
free(ps_out_buf);\
}\
\
if(pu1_bs_buf)\
free (pu1_bs_buf);\
\
exit(EXIT_SUCCESS);\
}\
}
void * ihevca_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size) {
(void) pv_ctxt;
return memalign(alignment, i4_size);
}
void ihevca_aligned_free(void *pv_ctxt, void *pv_buf) {
(void) pv_ctxt;
free(pv_buf);
return;
}
void flush_output(iv_obj_t *codec_obj, ivd_out_bufdesc_t *ps_out_buf,
UWORD8 *pu1_bs_buf, UWORD32 *pu4_op_frm_ts,
UWORD32 u4_ip_frm_ts, UWORD32 u4_bytes_remaining) {
WORD32 ret;
do {
ivd_ctl_flush_ip_t s_ctl_ip;
ivd_ctl_flush_op_t s_ctl_op;
if (*pu4_op_frm_ts >= (10000))
break;
s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_ctl_ip, (void *) &s_ctl_op);
if (IV_SUCCESS == ret) {
ivd_video_decode_ip_t s_video_decode_ip;
ivd_video_decode_op_t s_video_decode_op;
s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_video_decode_ip.u4_ts = u4_ip_frm_ts;
s_video_decode_ip.pv_stream_buffer = pu1_bs_buf;
s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining;
s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = BUF_LEN_0;
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = BUF_LEN_1;
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = 0;
s_video_decode_ip.s_out_buffer.pu1_bufs[0] =
ps_out_buf->pu1_bufs[0];
s_video_decode_ip.s_out_buffer.pu1_bufs[1] =
ps_out_buf->pu1_bufs[1];
s_video_decode_ip.s_out_buffer.pu1_bufs[2] = NULL;
s_video_decode_ip.s_out_buffer.u4_num_bufs = 2;
s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_video_decode_ip,
(void *) &s_video_decode_op);
if (1 == s_video_decode_op.u4_output_present) {
(*pu4_op_frm_ts)++;
}
}
} while (IV_SUCCESS == ret);
}
int main(WORD32 argc, CHAR *argv[]) {
WORD32 ret = 0;
UWORD32 file_pos = 0;
UWORD32 u4_ip_frm_ts = 0, u4_op_frm_ts = 0;
WORD32 u4_bytes_remaining = 0;
iv_obj_t *codec_obj = NULL;
if (argc < 2) {
return EXIT_SUCCESS;
}
ps_ip_file = fopen(argv[1], "rb");
if (NULL == ps_ip_file) {
return EXIT_SUCCESS;
}
/* Allocate input and output buffers for IV_YUV_420SP_UV */
{
pu1_bs_buf = (UWORD8 *) malloc(TOTAL_BUF_LEN);
ps_out_buf = (ivd_out_bufdesc_t *) malloc(sizeof(ivd_out_bufdesc_t));
if ((pu1_bs_buf == NULL) || (ps_out_buf == NULL)) {
EXIT_ON_ERROR(IV_FAIL)
}
ps_out_buf->pu1_bufs[0] = (UWORD8 *) malloc(TOTAL_BUF_LEN);
if (ps_out_buf->pu1_bufs[0] == NULL) {
EXIT_ON_ERROR(IV_FAIL)
}
memset(pu1_bs_buf, 0, TOTAL_BUF_LEN);
ps_out_buf->pu1_bufs[1] = ps_out_buf->pu1_bufs[0] + BUF_LEN_0;
}
/* Create decoder instance */
{
ihevcd_cxa_create_ip_t s_create_ip;
ihevcd_cxa_create_op_t s_create_op;
memset(&s_create_ip, 0, sizeof(ihevcd_cxa_create_ip_t));
memset(&s_create_op, 0, sizeof(ihevcd_cxa_create_op_t));
void *fxns = &ihevcd_cxa_api_function;
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
s_create_ip.s_ivd_create_ip_t.e_output_format = IV_YUV_420SP_UV;
s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ihevca_aligned_malloc;
s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ihevca_aligned_free;
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ihevcd_cxa_create_ip_t);
s_create_op.s_ivd_create_op_t.u4_size = sizeof(ihevcd_cxa_create_op_t);
ret = ihevcd_cxa_api_function(NULL, (void *) &s_create_ip,
(void *) &s_create_op);
EXIT_ON_ERROR(ret);
codec_obj = (iv_obj_t*) s_create_op.s_ivd_create_op_t.pv_handle;
codec_obj->pv_fxns = fxns;
codec_obj->u4_size = sizeof(iv_obj_t);
}
/* set num of cores */
{
ihevcd_cxa_ctl_set_num_cores_ip_t s_ctl_set_cores_ip;
ihevcd_cxa_ctl_set_num_cores_op_t s_ctl_set_cores_op;
s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_set_cores_ip.e_sub_cmd =
(IVD_CONTROL_API_COMMAND_TYPE_T) IHEVCD_CXA_CMD_CTL_SET_NUM_CORES;
s_ctl_set_cores_ip.u4_num_cores = 1;
s_ctl_set_cores_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_ip_t);
s_ctl_set_cores_op.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_ctl_set_cores_ip,
(void *) &s_ctl_set_cores_op);
EXIT_ON_ERROR(ret);
}
/* Set the decoder in frame decode mode */
{
ivd_ctl_set_config_ip_t s_ctl_ip;
ivd_ctl_set_config_op_t s_ctl_op;
s_ctl_ip.u4_disp_wd = 0;
s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_ctl_ip, (void *) &s_ctl_op);
EXIT_ON_ERROR(ret);
}
while ((u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8),
TOTAL_BUF_LEN, ps_ip_file))) {
{
ivd_video_decode_ip_t s_video_decode_ip;
ivd_video_decode_op_t s_video_decode_op;
s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_video_decode_ip.u4_ts = u4_ip_frm_ts;
s_video_decode_ip.pv_stream_buffer = pu1_bs_buf;
s_video_decode_ip.u4_num_Bytes = TOTAL_BUF_LEN;
s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = BUF_LEN_0;
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = BUF_LEN_1;
s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = 0;
s_video_decode_ip.s_out_buffer.pu1_bufs[0] =
ps_out_buf->pu1_bufs[0];
s_video_decode_ip.s_out_buffer.pu1_bufs[1] =
ps_out_buf->pu1_bufs[1];
s_video_decode_ip.s_out_buffer.pu1_bufs[2] = NULL;
s_video_decode_ip.s_out_buffer.u4_num_bufs = 2;
s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);
/* API Call: Video Decode */
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_video_decode_ip,
(void *) &s_video_decode_op);
if ((IV_SUCCESS != ret)
&& ((s_video_decode_op.u4_error_code & 0xFF)
== IVD_RES_CHANGED)) {
ivd_ctl_reset_ip_t s_ctl_ip;
ivd_ctl_reset_op_t s_ctl_op;
flush_output(codec_obj, ps_out_buf, pu1_bs_buf, &u4_op_frm_ts,
u4_ip_frm_ts, u4_bytes_remaining);
s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_ctl_ip,
(void *) &s_ctl_op);
EXIT_ON_ERROR(ret);
/* set num of cores */
{
ihevcd_cxa_ctl_set_num_cores_ip_t s_ctl_set_cores_ip;
ihevcd_cxa_ctl_set_num_cores_op_t s_ctl_set_cores_op;
s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_set_cores_ip.e_sub_cmd =
(IVD_CONTROL_API_COMMAND_TYPE_T) IHEVCD_CXA_CMD_CTL_SET_NUM_CORES;
s_ctl_set_cores_ip.u4_num_cores = 1;
s_ctl_set_cores_ip.u4_size =
sizeof(ihevcd_cxa_ctl_set_num_cores_ip_t);
s_ctl_set_cores_op.u4_size =
sizeof(ihevcd_cxa_ctl_set_num_cores_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_ctl_set_cores_ip,
(void *) &s_ctl_set_cores_op);
EXIT_ON_ERROR(ret);
}
}
file_pos += s_video_decode_op.u4_num_bytes_consumed;
fseek(ps_ip_file, file_pos, SEEK_SET);
u4_ip_frm_ts++;
if (1 == s_video_decode_op.u4_output_present) {
u4_op_frm_ts++;
} else {
if ((s_video_decode_op.u4_error_code >> IVD_FATALERROR) & 1) {
break;
}
}
}
}
/* To get the last decoded frames, call process with NULL input */
flush_output(codec_obj, ps_out_buf, pu1_bs_buf, &u4_op_frm_ts, u4_ip_frm_ts,
u4_bytes_remaining);
/* Delete decoder and close all the files and free all the memory */
{
ivd_delete_ip_t s_delete_dec_ip;
ivd_delete_op_t s_delete_dec_op;
s_delete_dec_ip.e_cmd = IVD_CMD_DELETE;
s_delete_dec_ip.u4_size = sizeof(ivd_delete_ip_t);
s_delete_dec_op.u4_size = sizeof(ivd_delete_op_t);
ret = ihevcd_cxa_api_function((iv_obj_t *) codec_obj,
(void *) &s_delete_dec_ip,
(void *) &s_delete_dec_op);
EXIT_ON_ERROR(ret);
}
return EXIT_SUCCESS;
}