10.1_demo/extern/qlibquammapi/sample/player/qua_player_sample2.c

319 lines
8.9 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include "utils/qua_display_parser.h"
#include "common/qua_sys_platform.h"
#include "system/qua_mm_system.h"
#include "player/qua_vppo_inf.h"
#include "player/qua_decoder_inf.h"
#include "player/qua_mm_player_common.h"
static QUA_VOID set_video_packet_default(qua_packet_t* pkt)
{
memset(pkt->data, 0x00, pkt->size);
pkt->offset = 0;
pkt->capacity = 0;
pkt->pts = -1;
pkt->dts = -1;
pkt->duration = 0;
pkt->baseTime = 0;
pkt->streamIndex = -1;
pkt->end_of_stream = 0;
}
static qua_packet_t *alloc_video_packet(QUA_U64 size)
{
qua_packet_t* pkt = (qua_packet_t*)calloc(1, sizeof(qua_packet_t));
if (pkt == NULL)
return NULL;
pkt->data = (uint8_t*)calloc(size, sizeof(uint8_t));
pkt->size = size;
set_video_packet_default(pkt);
return pkt;
}
static QUA_VOID free_video_packet(qua_packet_t *pkt)
{
if (pkt && pkt->data) {
free(pkt->data);
pkt->data = NULL;
}
free(pkt);
}
static int32_t qua_h2645_split_codec_nal(QUA_U8 *data, QUA_U32 size, QUA_U32 *nalSize) {
if (data == NULL || size < 4) {
return -1;
}
QUA_U8 nal_length = 4;
if (memcmp(data, "\x00\x00\x00\x01", 4)) {
if (memcmp(data, "\x00\x00\x01", 3)) {
return -1;
}
nal_length = 3;
}
if (size < 10) {
*nalSize = size;
return 0;
}
const QUA_U8 *nalu_data = data + nal_length;
QUA_U32 nalu_size = size - nal_length;
QUA_U8 *nextStart = NULL;
nextStart = (QUA_U8 *)memmem(nalu_data, nalu_size - 1, "\x00\x00\x00\x01", 4);
if (nextStart != NULL && nextStart < nalu_data + nalu_size - 4) {
*nalSize = nextStart - nalu_data + 4;
} else {
*nalSize = size;
}
return 0;
}
static const QUA_CHAR* display_id[] = {
"id:display0",
"id:display1",
"id:display2",
"id:display3",
};
int main(int argc, char *argv[])
{
QUA_S32 ret = 0;
qua_mm_system_t *system = NULL;
qua_mm_system_ops_t *sys_ops;
qua_mm_vo_device_t *vo_dev;
const qua_mm_module_t *disp_module = NULL;
qua_mm_device_t *mm_device = NULL;
qua_vo_pub_attr_t dev_attr = { 0 };
QUA_U32 blkSize;
qua_vb_config_t vbCfg;
QUA_CONST_CHAR *vo_id = NULL;
QUA_CONST_CHAR *fb_id = NULL;
QUA_S32 vo_num;
QUA_S32 fb_num;
QUA_S32 display_idx = 0;
QUA_VOID *video_dec = NULL;
QUA_VOID *display = NULL;
qua_video_config_t video_cfg;
qua_rect_t rect = { };
qua_video_frame_info_t video_frame_info;
qua_packet_t *video_pkt;
QUA_U32 buf_len = 0;
FILE *fp_strm = NULL;
char *chip_name = NULL;
char *os_name = NULL;
char *src_filename = NULL;
QUA_U64 pts = 0;
QUA_CHAR platform[32] = { 0 };
QUA_U32 used_bytes = 0;
chip_name = argv[1];
os_name = argv[2];
src_filename = argv[3];
// sys related
ret = qua_make_platform(chip_name, os_name, platform, sizeof(platform));
if (ret == QUA_FAILURE) {
printf("make platform name error!\n");
exit(1);
}
ret = qua_mm_init(QUA_TRUE, platform, &system);
if (ret != QUA_SUCCESS || system == NULL) {
printf("qua_mm_init error!\n");
return ret;
}
sys_ops = (qua_mm_system_ops_t *)system;
memset(&vbCfg, 0, sizeof(qua_vb_config_t));
blkSize = 1024;
vbCfg.max_pool_cnt = QUA_VB_MAX_POOLS;
vbCfg.common_pools[0].block_size = blkSize;
vbCfg.common_pools[0].block_cnt = 6;
ret = sys_ops->sys_init(&vbCfg);
if (ret != QUA_SUCCESS) {
printf("sys_init error!\n");
return ret;
}
// vo module related
ret = qua_mm_load_module(QUA_MM_MODULE_DISPLAY, &disp_module);
if (ret != QUA_SUCCESS || disp_module == NULL) {
printf("ret = %#x, get disp_module fail", ret);
exit(1);
}
mm_device = NULL;
qua_init_display_parser();
ret = qua_parse_display_id(display_id[display_idx], &vo_id, &vo_num, &fb_id, &fb_num);
printf("vo_id = %s vo_num = %d", vo_id, vo_num);
if (ret != QUA_SUCCESS) {
printf("%s display_id = %s error", __func__, display_id[display_idx]);
exit(1);
}
ret = disp_module->open_device(disp_module, vo_id, vo_num, &mm_device);
if (ret != QUA_SUCCESS || mm_device == NULL) {
printf("ret = %#x, get vo_dev fail", ret);
exit(1);
}
vo_dev = (qua_mm_vo_device_t *)mm_device;
dev_attr.intf_type = QUA_VO_INTF_LCD;
dev_attr.bg_color = 0xffffff;
dev_attr.intf_sync = QUA_VO_OUTPUT_1024x600_60; // no matters
ret = vo_dev->set_public_attr(vo_num, &dev_attr);
if (ret != QUA_SUCCESS) {
printf("vo_dev set attr fail ret = %#x", ret);
exit(1);
}
ret = vo_dev->enable(vo_num);
if (ret != QUA_SUCCESS) {
printf("vo_dev enable chn fail ret = %#x", ret);
exit(1);
}
// player start
fp_strm = fopen(src_filename, "rb");
if (fp_strm == NULL) {
printf("open file failed\n");
return -1;
}
// H264
video_dec = qua_decoder_create("video/avc", NULL);
if (video_dec == NULL) {
printf("qua_decoder_create failed\n");
return -1;
}
printf("qua_decoder_create ok\n");
display = qua_vppo_init("id:display0");
if (display == NULL) {
printf("qua_vppo_init failed\n");
return -1;
}
printf("qua_vppo_init ok\n");
video_cfg.width = 320;
video_cfg.height = 240;
video_cfg.fps = 25;
video_cfg.bitrate = 128000;
#if 0
video_cfg.profile = profile;
video_cfg.level = level;
// sps pps
if (extra_data_size > 0) {
memcpy(video_cfg.extra_data, (uint8_t*)extra_data, extra_data_size);
video_cfg.extra_data_size = extra_data_size;
}
#endif
ret = qua_decoder_prepare(video_dec, &video_cfg);
if (ret != 0) {
printf("qua_decoder_prepare failed\n");
return -1;
}
printf("qua_decoder_prepare ok\n");
rect.x = 0;
rect.y = 0;
rect.width = 320;
rect.height = 240;
qua_vppo_set_param(display, KEY_PARAMETER_VO_DISPLAY_RECT, (QUA_VOID_PTR)&rect);
qua_vppo_set_param(display, KEY_PARAMETER_VO_CHN_RECT, (QUA_VOID_PTR)&rect);
ret = qua_vppo_prepare(display);
if (ret != 0) {
printf("qua_vppo_prepare failed\n");
return -1;
}
printf("qua_vppo_prepare ok\n");
ret = qua_decoder_start(video_dec);
if ( ret!= 0) {
printf("qua_decoder_start failed\n");
return -1;
}
ret = qua_vppo_start(display);
if (ret != 0) {
printf("qua_vppo_start failed\n");
return -1;
}
// max input size
video_pkt = alloc_video_packet(video_cfg.width * video_cfg.height);
if (video_pkt == NULL) {
printf("alloc_video_packet failed\n");
return -1;
}
buf_len = video_cfg.width * video_cfg.height;
do {
QUA_U32 nalu_size = 0;
set_video_packet_default(video_pkt);
fseek(fp_strm, used_bytes, SEEK_SET);
QUA_U32 read_len = fread(video_pkt->data, 1, buf_len, fp_strm);
if (read_len == 0) {
printf("EOF\n");
used_bytes = 0;
continue;
}
qua_h2645_split_codec_nal(video_pkt->data, buf_len, &nalu_size);
used_bytes += nalu_size;
video_pkt->capacity = nalu_size;
video_pkt->dts = video_pkt->pts = pts;
pts += 40000;
ret = qua_decoder_queue_buffer(video_dec, video_pkt);
// if (ret != 0) {
// printf("qua_decoder_queue_buffer failed, ret = %#x\n", ret);
// if (ret == QUA_EAGAIN)
// continue;
// break;
// }
ret = qua_decoder_dequeue_buffer(video_dec, &video_frame_info);
if (ret != 0) {
printf("qua_decoder_dequeue_buffer warning, ret = %#x\n", ret);
} else {
ret = qua_vppo_send_frame(display, &video_frame_info);
if (ret != 0) {
printf("qua_vppo_send_frame failed, ret = %#x\n", ret);
break;
}
}
ret = qua_decoder_release_buffer(video_dec, &video_frame_info);
if (ret != 0) {
printf("qua_decoder_release_buffer failed, ret = %#x\n", ret);
break;
}
} while(1);
ret = qua_vppo_stop(display);
if (ret != 0) {
printf("qua_vppo_stop failed, ret = %#x\n", ret);
return -1;
}
ret = qua_decoder_stop(video_dec);
if (ret != 0) {
printf("qua_decoder_stop failed, ret = %#x\n", ret);
return -1;
}
qua_decoder_reset(video_dec);
qua_decoder_destroy(video_dec);
video_dec = NULL;
qua_vppo_reset(display);
qua_vppo_deinit(display);
display = NULL;
free_video_packet(video_pkt);
video_pkt = NULL;
if (fp_strm) {
fclose(fp_strm);
fp_strm = NULL;
}
// release vo device
if (vo_dev) {
vo_dev->disable(vo_num);
vo_dev->parent.close((qua_mm_device_t *)vo_dev);
vo_dev = NULL;
}
printf("well done\n");
return 0;
}