int mfcdec_basic(TUX_MFC_PARA *dec_para, int *force_exit) { int i=0; // Loop counter int pip; // Loop counter void *handle[NUM_PIPS]; void *fp[NUM_PIPS]; int nLoop; DWORD t1, t2, t_diff; // tick for performance measurement int perf_disp_period = 100; wchar_t str_performance[8]; float fps; BOOL eof_flag = FALSE; unsigned char *pStrmBuf[NUM_PIPS]; int nFrameLeng[NUM_PIPS]; unsigned char *pYUVBuf[NUM_PIPS]; int nYUVLeng[NUM_PIPS]; FRAMEX_CTX *pFrameExCtx[NUM_PIPS]; unsigned char *delimiter; int delimiter_leng; FP_LIST *pFP_LIST[NUM_PIPS]; // MFC APIÀÇ function pointers SSBSIP_H264_STREAM_INFO stream_info[NUM_PIPS]; //For output file! FILE *fp_out; //For output display! void *hRender_property=NULL; void *hRender[NUM_PIPS]; int render_wd=0, render_hi=0; SIZE_IMG_IDX size_img_idx; if (dec_para->num_pips > NUM_PIPS) { RETAILMSG(1,(L"num_pips must be less than or equal to %d.\n", NUM_PIPS)); return -1; } if( !dec_para->outDISP ) { fopen_s(&fp_out,dec_para->outfilename, "wb"); if (fp_out == NULL) { RETAILMSG(1,(L"Cannot open the output file.\n")); return 0; } } RETAILMSG(1,(L"\t ------------- \n")); //////////////////////// // Opening Input File // //////////////////////// for (pip=0; pip < dec_para->num_pips; pip++) { //fp[pip] = SSB_FILE_OPEN(pszFileName[pip]); fp[pip] = SSB_FILE_OPEN(dec_para->infilename[pip]); if (fp[pip] == NULL) { RETAILMSG(1,(L"File not found\n")); return 0; } switch (dec_para->codec_mode[pip]) { case CODEC_MPEG4: delimiter = delimiter_mpeg4; delimiter_leng = sizeof(delimiter_mpeg4); pFP_LIST[pip] = &(fp_list[0]); break; case CODEC_H263: delimiter = NULL; delimiter_leng = 0; pFP_LIST[pip] = &(fp_list[1]); break; case CODEC_H264: delimiter = delimiter_h264; delimiter_leng = sizeof(delimiter_h264); pFP_LIST[pip] = &(fp_list[2]); break; case CODEC_VC1: delimiter = NULL; delimiter_leng = 0; pFP_LIST[pip] = &(fp_list[3]); break; default: RETAILMSG(1,(L"[mfcdec_init] Undefined codec mode")); return -1; } /////////////////////////////////// // FrameExtractor Initialization // /////////////////////////////////// pFrameExCtx[pip] = FrameExtractorInit(FRAMEX_IN_TYPE_SEL, delimiter, delimiter_leng, 1); FrameExtractorFirst(pFrameExCtx[pip], fp[pip]); ////////////////////////////////////// /// 1. Create new instance /// ////////////////////////////////////// handle[pip] = pFP_LIST[pip]->fp_SsbSipDecodeInit(); if (handle[pip] == NULL) { RETAILMSG(1,(L"Decoder Init Failed.\n")); return 0; } ///////////////////////////////////////////// /// 2. Obtaining the Input Buffer /// /// (SsbSipH264DecodeGetInBuf) /// ///////////////////////////////////////////// pStrmBuf[pip] = (unsigned char *) pFP_LIST[pip]->fp_SsbSipDecodeDecodeGetInBuf(handle[pip], 204800); if (pStrmBuf[pip] == NULL) { RETAILMSG(1,(L"SsbSipDecodeGetInBuf Failed.\n")); pFP_LIST[pip]->fp_SsbSipDecodeDeInit(handle[pip]); return 0; } ////////////////////////////// // CONFIG stream extraction // ////////////////////////////// switch (dec_para->codec_mode[pip]) { case CODEC_MPEG4: nFrameLeng[pip] = ExtractConfigStreamMpeg4(pFrameExCtx[pip], fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; case CODEC_H263: nFrameLeng[pip] = ExtractConfigStreamH263(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; case CODEC_H264: nFrameLeng[pip] = ExtractConfigStreamH264(pFrameExCtx[pip], fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; case CODEC_VC1: nFrameLeng[pip] = ExtractConfigStreamVC1(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; } if (nFrameLeng[pip] == 0) { RETAILMSG(1, (L"\nFailed in extracting the CONFIG stream.")); return 0; } //////////////////////////////////////////////////////////////// /// 3. Configuring the instance with the config stream /// /// (SsbSipH264DecodeExe) /// //////////////////////////////////////////////////////////////// if (pFP_LIST[pip]->fp_SsbSipDecodeExe(handle[pip], nFrameLeng[pip]) != SSBSIP_H264_DEC_RET_OK) { RETAILMSG(1,(L"H.264 Decoder Configuration Failed.\n")); return 0; } ///////////////////////////////////// /// 4. Get stream information /// ///////////////////////////////////// switch (dec_para->codec_mode[pip]) { case CODEC_H264: pFP_LIST[pip]->fp_SsbSipDecodeGetConfig(handle[pip], H264_DEC_GETCONF_STREAMINFO, &(stream_info[pip])); break; case CODEC_VC1: pFP_LIST[pip]->fp_SsbSipDecodeGetConfig(handle[pip], VC1_DEC_GETCONF_STREAMINFO, &(stream_info[pip])); break; } pFP_LIST[pip]->fp_SsbSipDecodeGetConfig(handle[pip], H264_DEC_GETCONF_STREAMINFO, &(stream_info[pip])); RETAILMSG(1,(L"\n\t<STREAMINFO> width=%d height=%d.", stream_info[pip].width, stream_info[pip].height)); if( dec_para->outDISP ) { // Direct Draw surface creation // The surface size is determined by the input video stream // Because only one YV12 type surface is supported, // 0-th surface is assigned as YV12 surface and the others are asssigned as RGB565. if (pip == 0) { hRender[pip] = mfc_render_create_overlay(MFC_RENDER_SURFACE_TYPE_YV12, 0, 0, stream_info[pip].width, stream_info[pip].height, 800, 480); } else { hRender[pip] = mfc_render_create_overlay(MFC_RENDER_SURFACE_TYPE_RGB565, 0, 0, stream_info[pip].width, stream_info[pip].height, stream_info[pip].width, stream_info[pip].height); } if (hRender[pip] == NULL) { RETAILMSG(1, (L"\nMFC RENDER overlay surface [%d] creation failed.", pip)); return -1; } } } if( dec_para->outDISP ) { #if (PROPERTY_WINDOW == 1) hRender_property = mfc_render_create_overlay(MFC_RENDER_SURFACE_TYPE_RGB565,0, 0, PROPERTY_WINDOW_WIDTH, PROPERTY_WINDOW_HEIGHT, PROPERTY_WINDOW_WIDTH, PROPERTY_WINDOW_HEIGHT); if (hRender_property == NULL) { RETAILMSG(1, (L"\nMFC RENDER overlay property surface creation failed.")); return -1; } if (NumImg_MemLoad(character_img) == FALSE) { RETAILMSG(1, (L"\nMFC character image file cannot be found.")); return -1; } if (SizeImg_MemLoad(size_img) == FALSE) { RETAILMSG(1, (L"\nMFC size image file cannot be found.")); return -1; } memset(g_property_window, 0xFF, sizeof(g_property_window)); #endif // Performance display interval setting if ((stream_info[0].width == 320) && (stream_info[0].height == 240)) { size_img_idx = SIZE_IMG_QVGA; perf_disp_period = 200; } else if ((stream_info[0].width == 640) && (stream_info[0].height == 480)) { size_img_idx = SIZE_IMG_VGA; perf_disp_period = 100; } else if ((stream_info[0].width == 720) && (stream_info[0].height == 480)) { size_img_idx = SIZE_IMG_SD; perf_disp_period = 60; } else if ((stream_info[0].width == 720) && (stream_info[0].height == 576)) { size_img_idx = SIZE_IMG_SD; perf_disp_period = 60; } else { size_img_idx = SIZE_IMG_UNDEF; perf_disp_period = 100; } } else { //out File // Print Inteval of Performance value into colsole (Regardless of image size, it is set to fixed value.) perf_disp_period = 60; } RETAILMSG(1,(L"\nSTARTING MFC decoding (PIP=%d)\n", dec_para->num_pips)); t1 = GetTickCount(); nLoop=0; while( !eof_flag ) { nLoop++; if (*force_exit) { RETAILMSG(1,(L"\nFORCE EXIT\n")); break; } for (pip=0; pip < dec_para->num_pips; pip++) { ////////////////////////////////// /// 5. DECODE /// /// (SsbSipH264DecodeExe) /// ////////////////////////////////// if (pFP_LIST[pip]->fp_SsbSipDecodeExe(handle[pip], nFrameLeng[pip]) != SSBSIP_H264_DEC_RET_OK) { sprintf_s(msg,_countof(msg), "\n\t Error in decoding %d-th video, %d-th frame\n", pip, nLoop); LogMsg(); RETAILMSG(1,(L"\n-----------------------------\n")); RETAILMSG(1,(L"DECODE ERROR\n")); RETAILMSG(1,(L"DECODE ERROR\n")); RETAILMSG(1,(L"DECODE ERROR\n")); RETAILMSG(1,(L"DECODE ERROR\n")); RETAILMSG(1,(L"-----------------------------\n")); continue; } ////////////////////////////////////////////// /// 6. Obtaining the Output Buffer /// /// (SsbSipH264DecodeGetOutBuf) /// ////////////////////////////////////////////// pYUVBuf[pip] = (unsigned char *) pFP_LIST[pip]->fp_SsbSipDecodeDecodeGetOutBuf(handle[pip], (long *) &(nYUVLeng[pip])); RETAILMSG(0,(L"\t [%d] decoded.\n", nLoop)); /////////////////////// // Next VIDEO stream // /////////////////////// switch (dec_para->codec_mode[pip]) { case CODEC_VC1: nFrameLeng[pip] = NextFrameVC1(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; case CODEC_H263: nFrameLeng[pip] = NextFrameH263(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; default: nFrameLeng[pip] = pFP_LIST[pip]->fp_NextFrame(pFrameExCtx[pip], fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); } if (nFrameLeng[pip] < 4) { SSB_FILE_REWIND(fp[pip]); RETAILMSG(1,(L"\n### REWIND.\n")); switch (dec_para->codec_mode[pip]) { case CODEC_VC1: nFrameLeng[pip] = ExtractConfigStreamVC1(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; case CODEC_H263: nFrameLeng[pip] = ExtractConfigStreamH263(fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); break; default: FrameExtractorFirst(pFrameExCtx[pip], fp[pip]); nFrameLeng[pip] = pFP_LIST[pip]->fp_NextFrame(pFrameExCtx[pip], fp[pip], pStrmBuf[pip], INPUT_BUFFER_SIZE, NULL); } eof_flag = TRUE; } if( !dec_para->outDISP ) { fwrite(pYUVBuf[pip], 1, (size_t)nYUVLeng[pip], fp_out); //RETAILMSG(1,(L"\n Write File.\n")); } else { mfc_render_do(hRender[pip], pYUVBuf[pip], stream_info[pip].width, stream_info[pip].height, MFC_RENDER_IMAGE_TYPE_YUV420); mfc_render_flip(hRender[pip]); } } if (nLoop == perf_disp_period) { t2 = GetTickCount(); t_diff = t2 - t1; fps = (float)(1000 * nLoop) / t_diff; VERIFY(SUCCEEDED(StringCchPrintf(str_performance, _countof(str_performance) , L"%3.1f", fps))); RETAILMSG(1,(L"Disp. Perf. =%s fps\n", str_performance)); nLoop = 0; t1 = GetTickCount(); if( dec_para->outDISP ) { #if (PROPERTY_WINDOW == 1) SizeImg_Write(size_img_idx, (unsigned char *) g_property_window, PROPERTY_WINDOW_WIDTH, PROPERTY_WINDOW_HEIGHT, 10, 10); NumImg_Write_FPS(fps, (unsigned char *) g_property_window, PROPERTY_WINDOW_WIDTH, PROPERTY_WINDOW_HEIGHT, 90, 10); mfc_render_do(hRender_property, (unsigned char *) g_property_window, PROPERTY_WINDOW_WIDTH, PROPERTY_WINDOW_HEIGHT, MFC_RENDER_IMAGE_TYPE_RGB565); mfc_render_flip(hRender_property); #endif } } } for (pip=0; pip < dec_para->num_pips; pip++) { /////////////////////////////////////// /// 7. SsbSipH264DecodeDeInit /// /////////////////////////////////////// pFP_LIST[pip]->fp_SsbSipDecodeDeInit(handle[pip]); SSB_FILE_CLOSE(fp[pip]); if( !dec_para->outDISP ) { fclose(fp_out); RETAILMSG(1,(L"\n Close File.\n")); } else { mfc_render_delete_overlay(hRender[pip]); #if (PROPERTY_WINDOW == 1) mfc_render_delete_overlay(hRender_property); #endif } } RETAILMSG(1,(L"\n\n@@@ Decode Program ends.\n")); return 0; }
int Test_Display_H263(int argc, char **argv) { void *pStrmBuf; int nFrameLeng = 0; unsigned int pYUVBuf[2]; int is_first; struct pollfd test_fd; struct stat s; MMAP_STRM_PTR file_strm; SSBSIP_MPEG4_STREAM_INFO stream_info; s3c_pp_params_t pp_param; s3c_win_info_t osd_info_to_driver; struct fb_fix_screeninfo lcd_info; #ifdef FPS struct timeval start, stop; unsigned int time = 0; int frame_cnt = 0; #endif if(signal(SIGINT, sig_del_mpeg4) == SIG_ERR) { printf("Sinal Error\n"); } if (argc != 3) { printf("Usage : #./mfc <file name> <run mode>\n"); printf(" - <file name> : H.263 file to be displayed.\n"); printf(" - <run mode> : 0 (PP DMA Mode), 1 (PP FIFO Mode)\n"); return -1; } // in file open in_fd = open(argv[1], O_RDONLY); if(in_fd < 0) { printf("Input file open failed\n"); return -1; } // get input file size fstat(in_fd, &s); file_size = s.st_size; // mapping input file to memory in_addr = (char *)mmap(0, file_size, PROT_READ, MAP_SHARED, in_fd, 0); if(in_addr == NULL) { printf("input file memory mapping failed\n"); return -1; } // Post processor open pp_fd = open(PP_DEV_NAME, O_RDWR|O_NONBLOCK); if(pp_fd < 0) { printf("Post processor open error\n"); return -1; } // LCD frame buffer open fb_fd = open(FB_DEV_NAME, O_RDWR|O_NDELAY); if(fb_fd < 0) { printf("LCD frame buffer open error\n"); return -1; } ////////////////////////////////////// /// 1. Create new instance /// /// (SsbSipMPEG4DecodeInit) /// ////////////////////////////////////// handle = SsbSipMPEG4DecodeInit(); if (handle == NULL) { printf("H263_Dec_Init Failed.\n"); return -1; } ///////////////////////////////////////////// /// 2. Obtaining the Input Buffer /// /// (SsbSipMPEG4DecodeGetInBuf) /// ///////////////////////////////////////////// pStrmBuf = SsbSipMPEG4DecodeGetInBuf(handle, 200000); if (pStrmBuf == NULL) { printf("SsbSipMPEG4DecodeGetInBuf Failed.\n"); SsbSipMPEG4DecodeDeInit(handle); return -1; } //////////////////////////////////// // MPEG4 CONFIG stream extraction // //////////////////////////////////// file_strm.p_start = file_strm.p_cur = (unsigned char *)in_addr; file_strm.p_end = (unsigned char *)(in_addr + file_size); nFrameLeng = ExtractConfigStreamH263(&file_strm, pStrmBuf, INPUT_BUFFER_SIZE, NULL); //////////////////////////////////////////////////////////////// /// 3. Configuring the instance with the config stream /// /// (SsbSipMPEG4DecodeExe) /// //////////////////////////////////////////////////////////////// if (SsbSipMPEG4DecodeExe(handle, nFrameLeng) != SSBSIP_MPEG4_DEC_RET_OK) { printf("H.263 Decoder Configuration Failed.\n"); return -1; } ///////////////////////////////////// /// 4. Get stream information /// ///////////////////////////////////// SsbSipMPEG4DecodeGetConfig(handle, MPEG4_DEC_GETCONF_STREAMINFO, &stream_info); printf("\t<STREAMINFO> width=%d height=%d buf_width=%d buf_height=%d.\n", \ stream_info.width, stream_info.height, stream_info.buf_width, stream_info.buf_height); // set post processor configuration pp_param.src_full_width = stream_info.buf_width; pp_param.src_full_height = stream_info.buf_height; pp_param.src_start_x = 0; pp_param.src_start_y = 0; pp_param.src_width = pp_param.src_full_width; pp_param.src_height = pp_param.src_full_height; pp_param.src_color_space = YC420; pp_param.dst_start_x = 0; pp_param.dst_start_y = 0; pp_param.dst_full_width = FB0_WIDTH; // destination width pp_param.dst_full_height = FB0_HEIGHT; // destination height pp_param.dst_width = pp_param.dst_full_width; pp_param.dst_height = pp_param.dst_full_height; pp_param.dst_color_space = FB0_COLOR_SPACE; if ( atoi (argv[2]) == 0 ) pp_param.out_path = DMA_ONESHOT; else { pp_param.out_path = FIFO_FREERUN; pp_param.scan_mode = PROGRESSIVE_MODE; } ioctl(pp_fd, S3C_PP_SET_PARAMS, &pp_param); // get LCD frame buffer address fb_size = pp_param.dst_full_width * pp_param.dst_full_height* 2; // RGB565 #ifdef RGB24BPP fb_size = pp_param.dst_full_width * pp_param.dst_full_height * 4; // RGB888 #endif fb_addr = (char *)mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); if (fb_addr == NULL) { printf("LCD frame buffer mmap failed\n"); return -1; } osd_info_to_driver.Bpp = FB0_BPP; // RGB16 osd_info_to_driver.LeftTop_x = 0; osd_info_to_driver.LeftTop_y = 0; osd_info_to_driver.Width = FB0_WIDTH; // display width osd_info_to_driver.Height = FB0_HEIGHT; // display height // set OSD's information if(ioctl(fb_fd, SET_OSD_INFO, &osd_info_to_driver)) { printf("Some problem with the ioctl SET_OSD_INFO\n"); return -1; } ioctl(fb_fd, SET_OSD_START); if ( FIFO_FREERUN == pp_param.out_path ) { is_first = 1; } while(1) { #ifdef FPS gettimeofday(&start, NULL); #endif ////////////////////////////////// /// 5. DECODE /// /// (SsbSipMPEG4DecodeExe) /// ////////////////////////////////// if (SsbSipMPEG4DecodeExe(handle, nFrameLeng) != SSBSIP_MPEG4_DEC_RET_OK) break; ////////////////////////////////////////////// /// 6. Obtaining the Output Buffer /// /// (SsbSipMPEG4DecodeGetOutBuf) /// ////////////////////////////////////////////// SsbSipMPEG4DecodeGetConfig(handle, MPEG4_DEC_GETCONF_PHYADDR_FRAM_BUF, pYUVBuf); ///////////////////////////// // Next MPEG4 VIDEO stream // ///////////////////////////// nFrameLeng = NextFrameH263(&file_strm, pStrmBuf, INPUT_BUFFER_SIZE, NULL); if (nFrameLeng < 4) break; // Post processing // pp_param.SrcFrmSt에는 MFC의 output buffer의 physical address가 // pp_param.DstFrmSt에는 LCD frame buffer의 physical address가 입력으로 넣어야 한다. if ( FIFO_FREERUN == pp_param.out_path ) { if ( is_first ) { pp_param.src_buf_addr_phy = pYUVBuf[0]; ioctl(pp_fd, S3C_PP_SET_SRC_BUF_ADDR_PHY, &pp_param); ioctl(pp_fd, S3C_PP_START); is_first = 0; } else { pp_param.src_next_buf_addr_phy = pYUVBuf[0]; ioctl(pp_fd, S3C_PP_SET_SRC_BUF_NEXT_ADDR_PHY, &pp_param); } } else { pp_param.src_buf_addr_phy = pYUVBuf[0]; ioctl(pp_fd, S3C_PP_SET_SRC_BUF_ADDR_PHY, &pp_param); ioctl(fb_fd, FBIOGET_FSCREENINFO, &lcd_info); pp_param.dst_buf_addr_phy = lcd_info.smem_start; // LCD frame buffer ioctl(pp_fd, S3C_PP_SET_DST_BUF_ADDR_PHY, &pp_param); test_fd.fd = pp_fd; test_fd.events = POLLOUT|POLLERR; poll(&test_fd, 1, 3000); ioctl(pp_fd, S3C_PP_START); } #ifdef FPS gettimeofday(&stop, NULL); time += measureTime(&start, &stop); frame_cnt++; #endif } #ifdef FPS printf("Display Time : %u, Frame Count : %d, FPS : %f\n", time, frame_cnt, (float)frame_cnt*1000/time); #endif SsbSipMPEG4DecodeDeInit(handle); munmap(in_addr, file_size); munmap(fb_addr, fb_size); close(pp_fd); close(fb_fd); close(in_fd); return 0; }