Exemple #1
0
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;
}
Exemple #2
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;
}