This describe GM8126 ioctl functions: playback.c

GM8126 DVR

playback.c

/**
 * this sample code implement playback function, and playback for 20 seconds. 
 * demo file is CH0_video_0.avi, 
 * please put the demo file at the same directory with executed binary file.
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include "dvr_common_api.h"
#include "dvr_disp_api.h"
#include "dvr_enc_api.h"
#include "dvr_dec_api.h"
#include "gmavi_api.h"

int dvr_fd = 0;
int disp_fd = 0;
int dec_fd = 0 ;
int main_disp_no = 0;
int main_plane_id = 0;
int open_flag = 0;
int is_NTSC = TRUE;  

#define FUNCTION_NULL       -1
#define FUNCTION_NORMAL     0

int menu_func = FUNCTION_NULL;
#define USE_UPDATE_METHOD   1

unsigned char *pbbs_buf;
int dec_buf_size;
HANDLE  pb_file= NULL;
AviMainHeader pb_main_header;
AviStreamHeader pb_stream_header;
GmAviStreamFormat pb_stream_format;
int stream_id_pkt = 0;
struct pollfd dec_fds;
int is_st_vga = TRUE;

RECT D1_4CH[4] = {
        {  0,  0, 360,240},    {360,  0, 360,240},
        {  0,240, 360,240},    {360,240, 360,240}
        };
        
RECT VGA_4CH[4] = {
        {  0,  0, 640,360},    {512,  0, 640,360},
        {  0,360, 512,360},    {512,360, 512,360}
        };        

int do_disp_startup()
{
    int i, ret;
    dvr_disp_disp_param         disp_param;
    dvr_disp_update_disp_param  disp_update_param;
    dvr_disp_plane_param        plane_param[3];
    dvr_disp_update_plane_param plane_update_pa;
    dvr_disp_control    dsp_ctl;

    if (open_flag) {
        printf("multi open\n");
        return -1;
    }
    open_flag = 1;
    
    disp_fd = open("/dev/dvr_disp", O_RDWR);
    if (disp_fd < 0) {
        perror("Open failed:");
        open_flag = 0;
        return -1;
    }

    memset(&disp_param, 0x0, sizeof(dvr_disp_disp_param));
    memset(&disp_update_param, 0x0, sizeof(dvr_disp_update_disp_param));
    memset(plane_param, 0x0, sizeof(dvr_disp_plane_param) * 3);
    memset(&plane_update_pa, 0x0, sizeof(dvr_disp_update_plane_param));
    memset(&dsp_ctl, 0x0, sizeof(dvr_disp_control));
    
    main_disp_no = 0;

    // query LCD1 information
    disp_param.disp_num = main_disp_no;
    ret = ioctl(disp_fd, DVR_DISP_GET_DISP_PARAM, &disp_param);
    if (ret < 0)
        return -1;
    printf("LCD(%d): dim(%d-%d) res(in=%d,out=%d) plane_comb(%d) system(%d) mode(%d)\n",
        1, disp_param.dim.width, disp_param.dim.height, disp_param.res.input_res, disp_param.res.output_type,
        disp_param.plane_comb, disp_param.output_system, disp_param.output_mode);
    printf("       : color attrib.: br(%d)sa(%d)co(%d)-hus(%d)huc(%d)sh0(%d)sh1-(%d)shth0(%d)shth1(%d)\n",
        disp_param.color_attrib.brightness, disp_param.color_attrib.saturation, disp_param.color_attrib.contrast,
        disp_param.color_attrib.huesin, disp_param.color_attrib.huecos, disp_param.color_attrib.sharpnessk0,
        disp_param.color_attrib.sharpnessk1, disp_param.color_attrib.sharpness_thres0, disp_param.color_attrib.shaprness_thres1);
    printf("       : transparent: color1(%d,%d) color2(%d,%d)\n",
        disp_param.transparent_color[0].is_enable, disp_param.transparent_color[0].color,
        disp_param.transparent_color[1].is_enable, disp_param.transparent_color[1].color);
    usleep(100000);

#if USE_UPDATE_METHOD
    // set BG_AND_2PLANE, which means we need 1 background and another 2 planes
    disp_update_param.disp_num = main_disp_no;
    disp_update_param.param = DISP_PARAM_PLANE_COMBINATION;
    disp_update_param.val.plane_comb = BG_ONLY;//BG_AND_2PLANE;
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_DISP_PARAM, &disp_update_param);
    if (ret < 0)
        return -1;
    
    disp_update_param.disp_num = main_disp_no;
    disp_update_param.param = DISP_PARAM_OUTPUT_SYSTEM;

    disp_update_param.val.output_system = MCP_VIDEO_VGA;
    disp_update_param.val.display_rate = is_NTSC? 30 : 25;
    
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_DISP_PARAM, &disp_update_param);
    if (ret < 0)
        return -1;
    disp_update_param.param = DISP_PARAM_APPLY;
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_DISP_PARAM, &disp_update_param);
    if (ret < 0)
        return -1;
#else
    // set BG_AND_2PLANE, which means we need 1 background and another 2 planes
    disp_param.plane_comb = DISP_PARAM_PLANE_COMBINATION;
    ret = ioctl(disp_fd, DVR_DISP_SET_DISP_PARAM, &disp_param);
    if (ret < 0)
        return -1;
#endif
    // query 3 planes information
    for(i = 0; i < 3; i++) {
        plane_param[i].disp_num = main_disp_no;
        plane_param[i].plane_num = i;
        ret = ioctl(disp_fd, DVR_DISP_GET_PLANE_PARAM, &plane_param[i]);
        if (ret < 0)
            return -1;
        printf("LCD(%d)-plane(%d): ID(%d) rect(%d-%d,%d-%d) data_mode(%d) color_mode(%d)\n",
            main_disp_no, plane_param[i].plane_num, plane_param[i].param.plane_id, 
            plane_param[i].param.win.x, plane_param[i].param.win.y, plane_param[i].param.win.width, plane_param[i].param.win.height,
            plane_param[i].param.data_mode, plane_param[i].param.color_mode
            );
        usleep(50000);
        if (i == 0)
            main_plane_id = plane_param[i].param.plane_id;
    }

#if USE_UPDATE_METHOD
    // set color mode for background plane
    plane_update_pa.plane_id = plane_param[0].param.plane_id;
    plane_update_pa.param = PLANE_PARAM_COLOR_MODE;
    plane_update_pa.val.color_mode = LCD_COLOR_YUV422;
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_PLANE_PARAM, &plane_update_pa);
    if (ret < 0)
        return -1;

    // set data mode for background plane
    plane_update_pa.plane_id = plane_param[0].param.plane_id;
    plane_update_pa.param = PLANE_PARAM_DATA_MODE;
    plane_update_pa.val.data_mode = LCD_PROGRESSIVE;
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_PLANE_PARAM, &plane_update_pa);
    if (ret < 0)
        return -1;

    plane_update_pa.param = PLANE_PARAM_APPLY;
    ret = ioctl(disp_fd, DVR_DISP_UPDATE_PLANE_PARAM, &plane_update_pa);
    if (ret < 0)
        return -1;

#else /* USE_UPDATE_METHOD */
    plane_param[0].param.color_mode = LCD_COLOR_YUV422;
    plane_param[0].param.data_mode = LCD_PROGRESSIVE;
    ret = ioctl(disp_fd, DVR_DISP_SET_PLANE_PARAM, &plane_param[0]);
    if (ret < 0)
        return -1;
  
    ret = ioctl(disp_fd, DVR_DISP_SET_PLANE_PARAM, &plane_param[1]);
    if (ret < 0)
        return -1;
#endif /* USE_UPDATE_METHOD */
    return 0;
}

int do_disp_endup()
{
    if (!open_flag) {
        printf("Multi close\n");
        return -1;
    }           

    if (disp_fd > 0)
        close(disp_fd);
    
    disp_fd = 0;
    open_flag = 0;    
    
    return 0;
}

int open_pb_files(int ch_num, int index)
{
    int strh_count;
    char tmp_str[64];

    sprintf(tmp_str, "CH%d_video_%d.avi", ch_num, index);

    pb_file = GMAVIOpen(tmp_str, GMAVI_FILEMODE_READ, 0);
    if (!pb_file) {
        printf("Open [%s] failed!\n", tmp_str);
        return -1;
    }
    GMAVIGetAviMainHeader(pb_file, &pb_main_header);
    GMAVIGetStreamHeaderNum(pb_file, &strh_count);
    GMAVIGetStreamHeader(pb_file, 1/*get stream1*/, &pb_stream_header, &pb_stream_format, &stream_id_pkt);
    printf("dec type:<%c%c%c%c>\n",pb_stream_header.fccHandler[0]
                                ,pb_stream_header.fccHandler[1]
                                ,pb_stream_header.fccHandler[2]
                                ,pb_stream_header.fccHandler[3]);

    return 0;
}

void close_pb_files(int ch_num)
{    
    if(pb_file) {
        GMAVIClose(pb_file);
        pb_file = NULL;
    }
}

#define MAX_RECORD 4096
void packet_reader(int arg)
{
    int ret, ch_num;    
    int pb_idx = 0, pb_total = 0;    
    int pb_offset[MAX_RECORD] = {0};
    int reverse;
    dvr_enc_queue_get   data;
    unsigned char *buf;
    int buf_size = 0,intra = 0, backup_data = 0;    
    unsigned int i = 0;
    int file_idx = 1;
    dvr_dec_control    dec_ctrl;
    FuncTag tag;  
    struct timeval t1,t2;  

    memset(&dec_ctrl, 0x0, sizeof(dvr_dec_control));

    ch_num = arg;

    // prepare to select(or poll)
    dec_fds.fd = dec_fd;
    dec_fds.events = POLLIN;
    dec_fds.revents = 0;
  
    gettimeofday(&t1, NULL);        
  
    while(1) {
        gettimeofday(&t2, NULL);
    
        if ((t2.tv_sec - t1.tv_sec) == 20) {      //<playback for 20 seconds. then finish playback 
            break;               
        }     
        
        ret = poll(&dec_fds, 1, 2000);
        
        //(Dual8181) make request for playback data, then will call DVR_DEC_QUEUE_GET and DVR_DEC_QUEUE_PUT from message handler        
        ret = ioctl(dec_fd, DVR_DEC_QUEUE_GET, &data);
        backup_data = data.bs.length;
        if (ret < 0) {
            printf("buffer is not ready...\n");
            usleep(10000);
            continue;
        }
        
        buf = pbbs_buf + data.bs.offset;        
        
        // read bs(start)
        buf_size = backup_data;        
        reverse = 0;
        ret = GMAVIGetStreamDataAndIndex(pb_file, &stream_id_pkt, 
                buf, &buf_size, &intra, NULL, 0, i, reverse, &pb_offset[pb_idx]);
        if((intra == 1) && (pb_idx<MAX_RECORD))
            pb_total = (pb_idx++);       
                
        if (ret == GMSTS_END_OF_DATA) {
            printf("CH(%d,%d) - End of Playback!\n", ch_num, file_idx);
        
OPEN_PB_FILE_AGAIN:
            close_pb_files(ch_num);
            ret = open_pb_files(ch_num, file_idx++);
            if (ret < 0) {
                file_idx = 0;
                goto OPEN_PB_FILE_AGAIN;
            }
            GMAVISeek(pb_file, GMAVI_SEEK_TO_BEGINNING, NULL);

            //return job
            data.bs.length = 0;
            ret = ioctl(dec_fd, DVR_DEC_QUEUE_PUT, &data);
            if (ret < 0)
                printf("put failed when EOF...\n");

            dec_ctrl.command = DEC_UPDATE;
            dec_ctrl.src_param.dim.width = pb_main_header.dwWidth;
            dec_ctrl.src_param.dim.height = pb_main_header.dwHeight;
            dec_ctrl.src_param.win.x = 0;
            dec_ctrl.src_param.win.y = 0;
            dec_ctrl.src_param.win.width = pb_main_header.dwWidth;
            dec_ctrl.src_param.win.height = pb_main_header.dwHeight;
            dec_ctrl.src_param.bs_rate = (int) (1000000/(pb_main_header.dwMicroSecPerFrame));
            dec_ctrl.dst_param.plane_id = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.win.x = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.win.y = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.win.width = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.win.height = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.is_display = GMVAL_DO_NOT_CARE;
            dec_ctrl.dst_param.display_rate = GMVAL_DO_NOT_CARE;
           
            ret = ioctl(dec_fd, DVR_DEC_CONTROL, &dec_ctrl);
            if (ret < 0)
                printf("can't update playback parameters!");

            FN_RESET_TAG(&tag);
            FN_SET_PB_CH(&tag, ch_num);
            ioctl(dvr_fd, DVR_COMMON_APPLY, &tag);
            buf_size = 0;
            continue;
        }
        else if (ret < 0) 
            printf("CH(%d) - read error!\n", ch_num);

        data.bs.length = buf_size;        
        // read bs(end)
        ret = ioctl(dec_fd, DVR_DEC_QUEUE_PUT, &data);
        if (ret < 0) 
            printf("put failed...\n");                     
    }       
    
}

int do_pb_init(int ch_num)
{
    int ret;
    dvr_dec_channel_param   ch_param;

    memset(&ch_param, 0x0, sizeof(dvr_dec_channel_param));

    ret = open_pb_files(ch_num, 0);
    if (ret < 0)
        goto DO_PB_INIT_FAILED;    

    dec_fd = open("/dev/dvr_dec", O_RDWR);
    if (dec_fd < 0) {
        perror("Open [/dev/dvr_dec] failed:");
        goto DO_PB_INIT_FAILED;
    }
    
    switch(*(int *)pb_stream_header.fccHandler) {    
        case GMAVI_TYPE_H264: 
            ch_param.dec_type = ENC_TYPE_H264; 
            break;
        case GMAVI_TYPE_MPEG4:             
            ch_param.dec_type = ENC_TYPE_MPEG; 
            break;
        case GMAVI_TYPE_MJPEG: 
            ch_param.dec_type = ENC_TYPE_MJPEG;             
            break;
        default: 
            printf("%s:%d <dec_type err. %d>\n",__FUNCTION__,__LINE__, ch_param.dec_type);      
        return -1; 
    }

    ch_param.channel = ch_num; 
    ch_param.is_use_scaler = 1;
    ch_param.dec_param.output_type = DEC_OUTPUT_COLOR_YUV422;
    ch_param.scl_param.src_fmt = SCALE_YUV422;
    ch_param.scl_param.dst_fmt = SCALE_YUV422;
    ch_param.scl_param.scale_mode = SCALE_LINEAR;
    ch_param.scl_param.is_dither = 0;
    ch_param.scl_param.is_correction = 0;
    ch_param.scl_param.is_album = 1;
    ch_param.scl_param.des_level = 0;

    ret = ioctl(dec_fd, DVR_DEC_SET_CHANNEL_PARAM, &ch_param);
    if (ret < 0) {
        perror("Decoder DVR_DEC_SET_CHANNLE_PARAM failed:");
        goto DO_PB_INIT_FAILED;
    }

    ret = ioctl(dec_fd, DVR_DEC_QUERY_OUTPUT_BUFFER_SIZE, &dec_buf_size);
    if (ret < 0) {
        perror("Decoder DVR_DEC_QUERY_OUTPUT_BUFFER_SIZE failed:");
        goto DO_PB_INIT_FAILED;
    }
    
    pbbs_buf = (unsigned char*) mmap(NULL, dec_buf_size, PROT_READ|PROT_WRITE, MAP_SHARED, dec_fd, 0);
    if (pbbs_buf == MAP_FAILED) {
        perror("Dec mmap failed");
        goto DO_PB_INIT_FAILED;
    }
    return 0;

DO_PB_INIT_FAILED:
    if (dec_fd) {
        if (pbbs_buf) {
            munmap((void*)pbbs_buf, dec_buf_size);
            pbbs_buf = NULL;
        }
        close(dec_fd);
        dec_fd = 0;
    }
    if (pb_file) {
        GMAVIClose(pb_file);
        pb_file = NULL;
    }
    return -1;
}

int do_pb_start(int ch_num)
{
    int ret;
    dvr_dec_control    dec_ctrl;
    FuncTag tag;

    memset(&dec_ctrl, 0x0, sizeof(dvr_dec_control));

    if (!pb_file) {
        printf("Open file failed!\n");
        return -1;
    }
        
    dec_ctrl.command = DEC_START;
    dec_ctrl.src_param.dim.width = pb_main_header.dwWidth;
    dec_ctrl.src_param.dim.height = pb_main_header.dwHeight;
    dec_ctrl.src_param.win.x = 0;   //ROI, after decoder, or the input to scalar
    dec_ctrl.src_param.win.y = 0;   //ROI, after decoder, or the input to scalar
    dec_ctrl.src_param.win.width = pb_main_header.dwWidth;      //ROI, after decoder
    dec_ctrl.src_param.win.height = pb_main_header.dwHeight;    //ROI, after decoder
    dec_ctrl.src_param.bs_rate=(int) (1000000/(pb_main_header.dwMicroSecPerFrame));

    if(is_st_vga) {
        dec_ctrl.dst_param.win.x = VGA_4CH[ch_num].x;
        dec_ctrl.dst_param.win.y = VGA_4CH[ch_num].y;                    
    }           
    else {
        dec_ctrl.dst_param.win.x = D1_4CH[ch_num].x;    //final position of screen
        dec_ctrl.dst_param.win.y = D1_4CH[ch_num].y;    //final position of screen
    }
    dec_ctrl.dst_param.win.width = VGA_4CH[ch_num].width;      //final width in screen
    dec_ctrl.dst_param.win.height = VGA_4CH[ch_num].height;    //final width in screen
    dec_ctrl.dst_param.plane_id = main_plane_id;
    dec_ctrl.dst_param.is_display = TRUE;
    dec_ctrl.dst_param.display_rate = (is_NTSC)? 30 : 25;    
    
    ret = ioctl(dec_fd, DVR_DEC_CONTROL, &dec_ctrl);
    if (ret < 0)
        return -1;

    FN_RESET_TAG(&tag);
    FN_SET_PB_CH(&tag, ch_num);
    ret = ioctl(dvr_fd, DVR_COMMON_APPLY, &tag);
    if (ret < 0)
        return -1;    

    menu_func = FUNCTION_NORMAL;

    return 0;
}

int do_pb_stop(int ch_num)
{
    int ret;
    dvr_dec_control    dec_ctrl;
    FuncTag tag;

    memset(&dec_ctrl, 0x0, sizeof(dvr_dec_control));
    
    menu_func = FUNCTION_NULL;    
    dec_ctrl.command = DEC_STOP;
    if ((ret = ioctl(dec_fd, DVR_DEC_CONTROL, &dec_ctrl)) < 0)
        goto pb_exit;

    FN_RESET_TAG(&tag);
    FN_SET_PB_CH(&tag, ch_num);
    if ((ret = ioctl(dvr_fd, DVR_COMMON_APPLY, &tag)) < 0)
        goto pb_exit;

pb_exit:    
    return 0;
}

int do_pb_exit(int ch_num)
{
    if (dec_fd) {
        if (pbbs_buf) {
            munmap((void*)pbbs_buf, dec_buf_size);
            pbbs_buf = NULL;
        }
        close(dec_fd);        
        dec_fd = 0;
    }
    close_pb_files(ch_num);
    
    return 0;
}

int main(void)
{    
    //open dvr_common
    dvr_fd = open("/dev/dvr_common", O_RDWR);
    
    do_disp_startup();  
    do_pb_init(0);  
    do_pb_start(0);  
        
    packet_reader(0);
    
    do_pb_stop(0);  
    do_pb_exit(0);  
    do_disp_endup();  
    
    //close dvr_common
    close(dvr_fd);
    return 0;
}
Generated on Wed Jun 15 2011 15:50:59 for This describe GM8126 ioctl functions by  doxygen 1.7.1