예제 #1
0
파일: main.c 프로젝트: simbits/ClaudeGlass
gpointer display_thread(gpointer data)
{
    GCContext      *context             =  (GCContext*)data;
    GCConfig       *config              =  context->config;
    GCVDPAUContext *vdpau               = &context->VDPAU_context;
    Movie          *movie               =  context->movie_context;
    gint64          timeout             =  0;
    int             current_direction   =  DIRECTION_FORWARD;

    if (!context) 
        g_error("Missing context\n");

    movie->pre_load_surface  = vdpau->surface_queue.next;

    load_frame(context, movie->frame_offset, movie->pre_load_surface);
    
    do {
        movie->pre_load_surface = display_surface(context, movie->pre_load_surface);
        timeout = g_get_monotonic_time() + config->seconds_per_frame * G_TIME_SPAN_SECOND;

        g_mutex_lock(&movie->tick_lock);

        if (movie->ease_to) {
            movie->new_frame = FALSE;
            easeout_to_frame(context, movie->ease_to_frame, config->easing_factor);
            movie->ease_to = FALSE;
        }

        while (!movie->new_frame && !movie->ease_to && !context->exit) {
            if (!g_cond_wait_until(&movie->tick_cond, &movie->tick_lock, timeout)) {
                movie->frame_offset++;
                movie->fract_frame_count++;
                movie->play_direction = DIRECTION_FORWARD;
                movie->new_frame = TRUE;
                //g_message("tick: %lu", movie->frame_offset);
                break;
            }
        }

        movie->new_frame = FALSE;

        g_mutex_unlock(&movie->tick_lock);

        load_frame(context, movie->frame_offset, movie->pre_load_surface);
        
    } while (!context->exit);

    munmap(movie->planes, config->movie_size);
    close(movie->fd_movie);
    vdpau_exit(context);
    x11_exit(context);

    g_main_loop_quit(context->g_main_loop);

    return NULL;
}
예제 #2
0
파일: test.cpp 프로젝트: ceyusa/bgo685404
static gboolean
run_tests(gpointer data)
{
	struct xdata *xdata = static_cast<struct xdata*>(data);
	static bool xv = false;
	static int i = 0;

	char *filename = g_strconcat(formats[i++ % G_N_ELEMENTS(formats)],
				     ".rgb", NULL);
	load_frame(filename);

	if (frame)
		g_printerr("frame loaded: %s\n", filename);

	g_free(filename);

	if (create_xwindow(xv, xdata)) {
		xv = !xv;
		g_timeout_add(33, test, xdata);
		return FALSE;
	}

	g_printerr("xwin failed\n");
	destroy_xwindow(xdata);
	return TRUE;
}
예제 #3
0
파일: main.c 프로젝트: simbits/ClaudeGlass
unsigned long easeout_to_frame(GCContext *context, unsigned long destination_frame, int seconds)
{
    GCVDPAUContext  *vdpau   = &context->VDPAU_context;
    Movie           *movie   =  context->movie_context;
    unsigned long    frames  =  0;
    unsigned long    sf      =  movie->frame_offset;
    long             df      =  0;
    int              i       =  0;

//    GTimer *timer = g_timer_new();

    df = destination_frame - sf;
    frames = seconds * FPS;

//    g_timer_start(timer);
    for (i=0; i < frames; i++) {
        float c = (float)df * (powf((float)i / (float)frames - 1, 3) + 1);
        movie->frame_offset = sf + c;
        movie->fract_frame_count = movie->frame_offset;
        movie->pre_load_surface = display_surface(context, movie->pre_load_surface);
        load_frame(context, movie->frame_offset, movie->pre_load_surface);

        if (movie->new_frame)
            break;
    }
//    g_message("Ease done in %f seconds, at frame %lu", g_timer_elapsed(timer, NULL), movie->frame_offset);
//    g_timer_destroy(timer);


    return movie->frame_offset;
}
예제 #4
0
void
Metalib::reset ()
{ 
  Frame::reset ();
  load_frame_t load_frame = impl->load_frame;
  impl.reset (new Implementation (load_frame)); 
  load_frame (*this);
  impl->initialize (*this);
}
예제 #5
0
파일: cap.cpp 프로젝트: sangk54/mia
int V4LCapture::read_frame(uint8_t **data, struct v4l2_buffer *buf)
{
	if (param.replay_mode) {
		int ret = load_frame(&(buffers->start), &buf_now);
		*data = (uint8_t *) buffers->start;
		*buf = buf_now;
		return ret;
	}

	if( (int)buf_now.index != -1 ) {
		if( -1 == xioctl(fd, VIDIOC_QBUF, &buf_now) ){
			errno_exit("VIDIOC_QBUF");
		}
	}
	
	CLEAR( buf_now );

	buf_now.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	buf_now.memory = V4L2_MEMORY_MMAP;

	if( -1 == xioctl(fd, VIDIOC_DQBUF, &buf_now) ){
		if (EAGAIN == errno) {
			return -1;
			errno_exit("EAGAIN");
		} else if (EINVAL == errno) {
			errno_exit("EINVAL");
		} else if (ENOMEM == errno) {
			errno_exit("ENOMEM");
		} else if (EIO == errno) {
			errno_exit("EIO");
		} else {
			errno_exit("VIDIOC_DQBUF");
		}
	}
	
	struct buffer *pbuf = &buffers[buf_now.index];

	if (param.record_prefix != NULL) {
		dump_frame((uint8_t *)pbuf->start, &buf_now);
	}

	*data = (uint8_t *) pbuf->start;
	*buf = buf_now;

	return buf_now.bytesused;


}
예제 #6
0
int main(int argc, char *argv[]) {
	char line[PATH_MAX+10];
	SDL_Surface *screen;
	const SDL_VideoInfo* screen_info;
	struct frame first_frame = blank_frame;
	struct frame *current_frame = &first_frame;

	/* Initialize SDL */
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) {
		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}
	atexit(SDL_Quit);

	while(fgets(line, PATH_MAX+10, stdin)) {
		if(line[0] && line[0] != '\n') {
			load_frame(line, current_frame);
			current_frame->next = xmalloc(sizeof(*current_frame));
			*current_frame->next = blank_frame;
			current_frame->next->prev = current_frame;
			current_frame = current_frame->next;
		}
	}

	/* XXX Inefficient */
	current_frame->prev->next = NULL;

	/* Get screen resolution and initialize window */
	screen_info = SDL_GetVideoInfo();
	if(!screen_info) {
		fprintf(stderr, "SDL_GetVideoInfo: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}

	if(!(screen = SDL_SetVideoMode(screen_info->current_w, screen_info->current_h, 0, SDL_HWSURFACE))) {
		fprintf(stderr, "Unable to init SDL screen: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}

	/* Fake the first timer event */
	timer_event(0, &first_frame);

	/* Wait for exit events */
	while(1) {
		SDL_Rect rect;
		SDL_Event event;
		event.type = 0;
		if(!SDL_WaitEvent(&event)) {
			fprintf(stderr, "Unable to get event: %s\n", SDL_GetError());
			exit(EXIT_FAILURE);
		}
		switch(event.type) {
			case SDL_USEREVENT:
				switch(event.user.code) {
					case TIMER_EVENT:
						current_frame = event.user.data1;
						/* This may already be the last slide */
						if(!current_frame) {
							goto mainloopend;
						}

						/* Calculate where to draw the image */
						rect.x = (screen->w/2)-current_frame->image->w;
						rect.y = (screen->h/2)-current_frame->image->h;
						rect.w = current_frame->image->w;
						rect.h = current_frame->image->h;

						/* Redraw dirtied background */
						if(SDL_FillRect(screen, &rect, 0) != 0) {
							fprintf(stderr, "Unable to draw rectangle: %s\n", SDL_GetError());
							exit(EXIT_FAILURE);
						}

						/* Draw image */
						if(SDL_BlitSurface(current_frame->image, NULL, screen, &rect) != 0) {
							fprintf(stderr, "Unable to blit frame: %s\n", SDL_GetError());
							exit(EXIT_FAILURE);
						}

						/* Update dirty rects */
						SDL_UpdateRects(screen, 1, &rect);

						/* Wait until this slide is done before advancing */
						SDL_AddTimer(current_frame->length*1000, &timer_event, current_frame->next);
						break;
				}
				break;
			case SDL_QUIT:
				goto mainloopend;
		}
	}
mainloopend:

	exit(EXIT_SUCCESS);
}
예제 #7
0
int
mfx_encode(int cid) {
	mfxStatus sts = MFX_ERR_NONE;
	mfxSyncPoint vppsync = NULL;
	mfxSyncPoint encsync = NULL;
	mfxFrameInfo vppdefinfo;
	unsigned long long id = 0;
	unsigned long long fpsunit = 90000 / fps;
	memset(&vppdefinfo, 0, sizeof(vppdefinfo));
	vppdefinfo.PicStruct		= MFX_PICSTRUCT_PROGRESSIVE;
	vppdefinfo.FourCC		= MFX_FOURCC_YV12;	// the only difference
	vppdefinfo.ChromaFormat		= MFX_CHROMAFORMAT_YUV420;
	vppdefinfo.Width		= MFX_ALIGN16(w);
	vppdefinfo.Height		= MFX_ALIGN16(h);
	vppdefinfo.CropW		= w;
	vppdefinfo.CropH		= h;
	vppdefinfo.FrameRateExtN	= fps;
	vppdefinfo.FrameRateExtD	= 1;
	//
	while(sts >= MFX_ERR_NONE || sts == MFX_ERR_MORE_DATA) {
		mfxFrameSurface1 *svppin, *svppout;
		int framesize;
		unsigned char *frame = load_frame(&framesize);
		//
		if(frame == NULL) {
			ga_error("END-OF-FRAME\n");
			break;
		}
		//
		svppin  = frame_pool_get(_vpppool[cid][0], &_vppresponse[cid][0]);
		svppout = frame_pool_get(_vpppool[cid][1], &_vppresponse[cid][1]);
		if(svppin == NULL || svppout == NULL) {
			ga_error("No surface available (%p, %p)\n", svppin, svppout);
			break;
		}
		if(fa_lock(NULL, svppin->Data.MemId, &svppin->Data) != MFX_ERR_NONE) {
			ga_error("Unable to lock VPP frame\n");
			break;
		}
		// fill frame info
		memcpy(&svppin->Info,  &vppdefinfo, sizeof(mfxFrameInfo));
		memcpy(&svppout->Info, &vppdefinfo, sizeof(mfxFrameInfo));
		svppin->Info.FourCC  = MFX_FOURCC_YV12;
		svppout->Info.FourCC = MFX_FOURCC_NV12;
		svppin->Data.TimeStamp = id * fpsunit;
		id++;
		//ga_error("In timestamp = %llu\n", svppin->Data.TimeStamp);
		// copy the frame
		do {
			mfxU8 *dst;
			int i, w2 = w/2, h2 = h/2, p2 = svppin->Data.Pitch/2;
			unsigned char *src = frame;
			// Copy Y
			for(dst = svppin->Data.Y, i = 0; i < h; i++) {
				memcpy(dst, src, w);
				dst += svppin->Data.Pitch;
				src += w;
			}
			// Copy U
			for(dst = svppin->Data.U, i = 0; i < h2; i++) {
				memcpy(dst, src, w2);
				dst += p2;
				src += w2;
			}
			// Copy V
			for(dst = svppin->Data.V, i = 0; i < h2; i++) {
				memcpy(dst, src, w2);
				dst += p2;
				src += w2;
			}
		} while(0);
		//
		if(fa_unlock(NULL, svppin->Data.MemId, &svppin->Data) != MFX_ERR_NONE) {
			ga_error("Unable to unlock VPP frame\n");
			break;
		}
		// do VPP
		sts = mfx_encode_vpp(_session[cid], svppin, svppout, &vppsync);
		// VPP errors?
		if(sts == MFX_ERR_MORE_DATA)	continue;
		if(sts == MFX_ERR_MORE_SURFACE)	continue;
		if(sts != MFX_ERR_NONE) {
			mfx_invalid_status(sts);
			ga_error("video encoder: VPP failed.\n");
			break;
		}
		//
		//MFXVideoCORE_SyncOperation(_session[cid], vppsync, MFX_INFINITE);
		// do ENCODE
		sts = mfx_encode_encode(_session[cid], svppout, &_mfxbs[cid], &encsync);
		//
		if(sts == MFX_ERR_MORE_DATA)	continue;
		if(sts != MFX_ERR_NONE) {
			mfx_invalid_status(sts);
			ga_error("video encoder: encode failed.\n");
			break;
		}
		//
		//ga_error("Out timestamp = d:%lld t:%llu\n", _mfxbs[cid].DecodeTimeStamp, _mfxbs[cid].TimeStamp);
		// save frame
		MFXVideoCORE_SyncOperation(_session[cid], encsync, MFX_INFINITE);
#if 1
		unsigned char *ptr = _mfxbs[cid].Data, *nextptr;
		int naltype, nalsize, nali = 0;
		int off, nextoff;
		// each frame can have only 1 nal ...
		if(ptr != NULL)
			ptr += _mfxbs[cid].DataOffset;
		off = nextoff = 4;
		while(ptr != NULL) {
			// search for startcode 00 00 01 or 00 00 00 01
			for(nextptr = ptr+3;
					nextptr < _mfxbs[cid].Data+_mfxbs[cid].DataOffset+_mfxbs[cid].DataLength-4;
					nextptr++) {
				if(*nextptr == 0 && *(nextptr+1) == 0) {
					if(*(nextptr+2) == 1) {
						// 00 00 01
						nextoff = 3;
						break;
					} else if(*(nextptr+2) == 0 && *(nextptr+3) == 1) {
						// 00 00 00 01
						nextoff = 4;
						break;
					}
				}
			}
			//
			if(nextptr < _mfxbs[cid].Data+_mfxbs[cid].DataOffset+_mfxbs[cid].DataLength-4) {
				nalsize = nextptr - ptr;
				ga_error("XXX: nal[%d] type=%d size=%d\n", nali, *(ptr+off) & 0x1f, nalsize);
				ptr = nextptr;
			} else {
				nalsize = _mfxbs[cid].Data+_mfxbs[cid].DataOffset+_mfxbs[cid].DataLength-ptr;
				ga_error("XXX: nal[%d] type=%d size=%d\n", nali, *(ptr+off) & 0x1f, nalsize);
				ptr = NULL;
			}
			nali++;
			off = nextoff;
		};
#endif
		write_frame(_mfxbs[cid].Data, _mfxbs[cid].DataLength);
		_mfxbs[cid].DataLength = _mfxbs[cid].DataOffset = 0;
	}
	//
	while(sts >= MFX_ERR_NONE) {
		sts = mfx_encode_encode(_session[cid], NULL, &_mfxbs[cid], &encsync);
	}
	//
	return 0;
}
예제 #8
0
파일: yay.c 프로젝트: MayRiv/Yuv-Streamer
int main(int argc, char *argv[])
{
	int     opt;
	char    caption[32];
	regex_t reg;
	regmatch_t pm;
	int     result;
	char    picsize[32]="";
	int     used_s_opt = 0;
	int     play_yuv = 0;
	unsigned int start_ticks = 0;
	Uint32 vflags;

	if (argc == 1) {
		print_usage();
		return 1;
	} else {
		while((opt = getopt(argc, argv, "f:s:")) != -1)
			switch(opt){
				case 's':
					if (sscanf(optarg, "%dx%d", &width, &height) != 2) {
						fprintf(stdout, "No geometry information provided by -s parameter.\n");
						return 1;
					}
					used_s_opt = 1;
					break;
				case 'f':
					if (sscanf(optarg, "%d", &cfidc) != 1 || (cfidc<0 && cfidc>3)) {
						fprintf(stdout, "Invalid format provided by -f parameter.\n");
						return 1;
					}
					break;
				default:
					print_usage();
					return 1;
					break;
			}
	}
	argv += optind;
	argc -= optind;

	vfilename = argv[0];

	if(!used_s_opt) {
		// try to find picture size from filename or path
		if (regcomp(&reg, "_[0-9]+x[0-9]+", REG_EXTENDED) != 0) return -1;
		result = regexec(&reg, vfilename, 1, &pm, REG_NOTBOL);
		if(result == 0){
			strncpy(picsize, (vfilename + pm.rm_so + 1), (pm.rm_eo - pm.rm_so -1 ));
			strcat(picsize, "\0");
		}
		if (sscanf(picsize, "%dx%d", &width, &height) != 2) {
			fprintf(stdout, "No geometry information found in path/filename.\nPlease use -s <width>x<height> paramter.\n");
			return 1;
		}
	}
	// some WM can't handle small windows...
	if (width < 100){
		zoom = 2;
		min_zoom = 2;
	}
	//printf("using x=%d y=%d\n", width, height);

	// SDL init
	if(SDL_Init(SDL_INIT_VIDEO) < 0){ 
		fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
		exit(1);
	}
	atexit(SDL_Quit); 

	info = SDL_GetVideoInfo();
	if( !info ) 
	{      fprintf(stderr, "SDL ERROR Video query failed: %s\n", SDL_GetError() );
		SDL_Quit(); exit(0); 
	}

	bpp = info->vfmt->BitsPerPixel;
	if(info->hw_available)
		vflags = SDL_HWSURFACE;
	else	
		vflags = SDL_SWSURFACE;

	if( (screen = SDL_SetVideoMode(width*zoom, height*zoom, bpp,
					vflags)) == 0 ) 
	{       
		fprintf(stderr, "SDL ERROR Video mode set failed: %s\n", SDL_GetError() );
		SDL_Quit(); exit(0); 
	}


	// DEBUG output
	// printf("SDL Video mode set successfully. \nbbp: %d\nHW: %d\nWM: %d\n", 
	// 	info->vfmt->BitsPerPixel, info->hw_available, info->wm_available);


	SDL_EnableKeyRepeat(500, 10);

	my_overlay = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);
	if(!my_overlay){ //Couldn't create overlay?
		fprintf(stderr, "Couldn't create overlay\n"); //Output to stderr and quit
		exit(1);
	}

	/* should allocate memory for y_data, cr_data, cb_data here */
	y_data  = malloc(width * height * sizeof(Uint8));
	if (cfidc > 0)
	{
		cb_data = malloc(width * height * sizeof(Uint8) / SubSizeC[cfidc]);
		cr_data = malloc(width * height * sizeof(Uint8) / SubSizeC[cfidc]);
	}

	fpointer = fopen(vfilename, "rb"); 
	if (fpointer == NULL){
		fprintf(stderr, "Error opening %s\n", vfilename);
		return 1;
	}
	// send event to display first frame
	event.type = SDL_KEYDOWN;
	event.key.keysym.sym = SDLK_RIGHT;
	SDL_PushEvent(&event);

	// main loop
	while (!quit){
		sprintf(caption, "frame %d, zoom=%d", frame, zoom);
		SDL_WM_SetCaption( caption, NULL );

		// wait for SDL event
		SDL_WaitEvent(&event);

		switch(event.type)
		{
			case SDL_KEYDOWN: 
				switch(event.key.keysym.sym)
				{
					case SDLK_SPACE:
						{
							play_yuv = 1; // play it, sam!
							while(play_yuv){
								start_ticks = SDL_GetTicks();
								sprintf(caption, "frame %d, zoom=%d", frame, zoom);
								SDL_WM_SetCaption( caption, NULL );

								// check for next frame existing
								if(load_frame()){
									draw_frame();
									//insert delay for real time viewing
									if(SDL_GetTicks() - start_ticks < 40)
										SDL_Delay(40 - (SDL_GetTicks() - start_ticks));
									frame++;
								} else {
									play_yuv = 0;
								}
								// check for any key event
								if(SDL_PollEvent(&event)){
									if(event.type == SDL_KEYDOWN){
										// stop playing
										play_yuv = 0;
									}
								}
							}
							break;
						}
					case SDLK_RIGHT: 
						{
							// check for next frame existing
							if(load_frame()){
								draw_frame();
								frame++;
							}

							break;
						} 
					case SDLK_BACKSPACE:
					case SDLK_LEFT:
						{ 
							if(frame>1){
								frame--;
								fseek(fpointer, ((frame-1)*height*width*FrameSize2C[cfidc])/2 , SEEK_SET);
								//if(draw_frame())
								load_frame();
								draw_frame();
							}
							break;
						}
					case SDLK_UP:
						{
							zoom++;
							screen = SDL_SetVideoMode(width*zoom, height*zoom, bpp,
									vflags); 
							video_rect.w = width*zoom;
							video_rect.h = height*zoom;
							SDL_DisplayYUVOverlay(my_overlay, &video_rect);
							break;
						}
					case SDLK_DOWN:
						{
							if(zoom>min_zoom){
								zoom--;
								screen = SDL_SetVideoMode(width*zoom, height*zoom, bpp,
										vflags); 
								video_rect.w = width*zoom;
								video_rect.h = height*zoom;
								SDL_DisplayYUVOverlay(my_overlay, &video_rect);
							}
							break;
						}
					case SDLK_r:
						{ 
							if(frame>1){
								frame=1;
								fseek(fpointer, 0, SEEK_SET);
								//if(draw_frame())
								load_frame();
								draw_frame();
							}
							break;
						}
					case SDLK_g:
						grid = ~grid;
						draw_frame();
						break;
					case SDLK_q:
						quit = 1;
						break;
					case SDLK_f:
						SDL_WM_ToggleFullScreen(screen);
						break;
					default:
						break;
				} // switch key
				break;
			case SDL_QUIT:
				quit = 1;
				break;
			case SDL_VIDEOEXPOSE:
				SDL_DisplayYUVOverlay(my_overlay, &video_rect);
				break;
			default:
				break;

		} // switch event type

	} // while
	// clean up
	SDL_FreeYUVOverlay(my_overlay); 
	free(y_data);
	free(cb_data);
	free(cr_data);
	fclose(fpointer);
	if (!used_s_opt)
		regfree(&reg);

	return 0;
}
예제 #9
0
파일: display.c 프로젝트: jmptable/a-demo
int main(int argc, char* argv[]) {
    // parse cli arguments

    char* filepath;

    if (argc == 2) {
        filepath = argv[1];
    } else {
        printf("usage: %s some-led-data.dat\n", argv[0]);
        exit(1);
    }

    prussdrv_init();

    int ret = prussdrv_open(PRU_EVTOUT_0);
    if (ret) {
        printf("prussdrv_open open failed\n");
        exit(1);
    }

    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
    prussdrv_pruintc_init(&pruss_intc_initdata);

    // initialize memory shared between PRU and host application
    init_memory();

    // initialize interface to PRU
    pru_ctrl_init(mem_fd);

    // put the LED data in the file where the PRU can get it
    load_frame(filepath);

    // tell the PRU where to find the data
    pru_write_reg(REG_ADDRESS, (uint32_t)get_ddr_address());

    // tell the PRU how many slices we have
    pru_write_reg(REG_SLICE_TOTAL, sliceCount);

    // display!
    ret = prussdrv_exec_program(PRU_NUM, "./driver.bin");
    if (ret == -1) {
        printf("failed to open driver.bin\n");
        exit(1);
    }
    printf("running...\nhit enter to stop.\n");
    getchar(); // stall until enter is hit

    // cleanup

    // disable pru
    prussdrv_pru_disable(PRU_NUM);
    
    // exit PRU interfaces
    prussdrv_exit();
    pru_ctrl_exit();

    // undo memory mapping
    munmap(ddrMem, get_ddr_size());
    close(mem_fd);

    return 0;
}
예제 #10
0
static int
app_run (App * app)
{
  GstVaapiImage *image;
  GstVaapiVideoPool *pool;
  GThread *buffer_thread;
  gsize id;
  int ret = EXIT_FAILURE;

  image = gst_vaapi_image_new (app->display, GST_VIDEO_FORMAT_I420,
      app->parser->width, app->parser->height);

  {
    GstVideoInfo vi;
    gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_ENCODED,
        app->parser->width, app->parser->height);
    pool = gst_vaapi_surface_pool_new_full (app->display, &vi, 0);
  }

  buffer_thread = g_thread_new ("get buffer thread", get_buffer_thread, app);

  while (1) {
    GstVaapiSurfaceProxy *proxy;
    GstVaapiSurface *surface;

    if (!load_frame (app, image))
      break;

    if (!gst_vaapi_image_unmap (image))
      break;

    proxy =
        gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL (pool));
    if (!proxy) {
      g_warning ("Could not get surface proxy from pool.");
      break;
    }
    surface = gst_vaapi_surface_proxy_get_surface (proxy);
    if (!surface) {
      g_warning ("Could not get surface from proxy.");
      break;
    }

    if (!gst_vaapi_surface_put_image (surface, image)) {
      g_warning ("Could not update surface");
      break;
    }

    if (!upload_frame (app->encoder, proxy)) {
      g_warning ("put frame failed");
      break;
    }

    app->read_frames++;
    id = gst_vaapi_surface_get_id (surface);
    g_debug ("input frame %d, surface id = %" G_GSIZE_FORMAT, app->read_frames,
        id);

    gst_vaapi_surface_proxy_unref (proxy);
  }

  app->input_stopped = TRUE;

  g_thread_join (buffer_thread);

  if (!app->encode_failed && feof (app->parser->fp))
    ret = EXIT_SUCCESS;

  gst_vaapi_video_pool_replace (&pool, NULL);
  gst_vaapi_object_unref (image);
  return ret;
}