Пример #1
0
image_t *
get_next_frame (bool_t store_wfa, int enlarge_factor,
		int smoothing, const char *reference_frame,
		format_e format, video_t *video, dectimer_t *timer,
		wfa_t *orig_wfa, bitfile_t *input)
/*
 *  Get next frame of the WFA 'video' from stream 'input'.
 *  'orig_wfa' is the constant part of the WFA used by all frames.
 *  Depending on values of 'enlarge_factor' and 'smoothing' enlarge and
 *  smooth image, respectively. 
 *  If 'store_wfa' is TRUE, then store WFA structure of reference frames
 *  (used by analysis tool xwfa).
 *  If 'reference_frame' is not NULL, then load image 'reference_frame'
 *  from disk.
 *  'format' gives the color format to be used (either 4:2:0 or 4:4:4).
 *  If 'timer' is not NULL, then accumulate running time statistics. 
 *
 *  Return value:
 *	pointer to decoded frame
 *
 *  Side effects:
 *	'video' and 'timer' struct are modified.
 */
{
   image_t *frame 			  = NULL; /* current frame */
   image_t *sframe 			  = NULL; /* current smoothed frame */
   bool_t   current_frame_is_future_frame = NO;

   if (video->future_display == video->display)	 
   {
      /*
       *  Future frame is already computed since it has been used
       *  as reference frame. So just return the stored frame.
       */
      if (video->frame) /* discard current frame */
	 free_image (video->frame);
      video->frame  = video->future;
      video->future = NULL;

      if (video->sframe) /* discard current (smoothed) frame */
	 free_image (video->sframe);
      video->sframe  = video->sfuture;
      video->sfuture = NULL;

      if (store_wfa)
	 copy_wfa (video->wfa, video->wfa_future);

      video->display++;

      if (!store_wfa)
	 video->wfa = NULL;
   }
   else
   {
      do				/* compute next frame(s) */
      {
	 unsigned      frame_number;	/* current frame number */
	 clock_t       ptimer;
	 unsigned int  stop_timer [3];
	 wfa_t	      *tmp_wfa = NULL;
	 
	 if (!store_wfa)
	    video->wfa = orig_wfa;
	 else
	 {
	    tmp_wfa = alloc_wfa (NO);
	    copy_wfa (tmp_wfa, video->wfa);
	    copy_wfa (video->wfa, orig_wfa);
	 }
   
	 /*
	  *  First step: read WFA from disk
	  */
	 prg_timer (&ptimer, START);
	 frame_number = read_next_wfa (video->wfa, input);
	 stop_timer [0] = prg_timer (&ptimer, STOP);
	 if (timer)
	 {
	    timer->input [video->wfa->frame_type] += stop_timer [0];
	    timer->frames [video->wfa->frame_type]++;
	 }
      
	 /*
	  *  Read reference frame from disk if required
	  *  (i.e., 1st frame is of type B or P)
	  */
	 if (video->display == 0 && video->wfa->frame_type != I_FRAME)
	 {
	    if (!reference_frame)
	       error ("First frame is %c-frame but no "
		      "reference frame is given.",
		      video->wfa->frame_type == B_FRAME ? 'B' : 'P');

	    video->frame  = read_image_file (reference_frame);
	    video->sframe = NULL;
	 }
   
	 /*
	  *  Depending on current frame type update past and future frames
	  */
	 if (video->wfa->frame_type == I_FRAME)
	 {
	    if (video->past)		/* discard past frame */
	       free_image (video->past);
	    video->past = NULL;
	    if (video->future)		/* discard future frame */
	       free_image (video->future);
	    video->future = NULL;
	    if (video->sfuture)		/* discard (smoothed) future frame */
	       free_image (video->sfuture);
	    video->sfuture = NULL;
	    if (video->frame)		/* discard current frame */
	       free_image (video->frame);
	    video->frame = NULL;
	    if (video->sframe)		/* discard current (smoothed) frame */
	       free_image (video->sframe);
	    video->sframe = NULL;
	 }
	 else if (video->wfa->frame_type == P_FRAME)
	 {
	    if (video->past)		/* discard past frame */
	       free_image (video->past);
	    video->past = video->frame;	/* past <- current frame */
	    video->frame = NULL;
	    if (video->sframe)		/* discard current (smoothed) frame */
	       free_image (video->sframe);
	    video->sframe = NULL;
	    if (store_wfa)
	       copy_wfa (video->wfa_past, tmp_wfa);
	    if (video->future)		/* discard future frame */
	       free_image (video->future);
	    video->future = NULL;
	    if (video->sfuture)		/* discard (smoothed) future frame */
	       free_image (video->sfuture);
	    video->sfuture = NULL;
	 }
	 else				/* B_FRAME */
	 {
	    if (current_frame_is_future_frame)
	    {
	       if (video->future)	/* discard future frame */
		  free_image (video->future);
	       video->future = frame;	/* future <- current frame */
	       if (video->sfuture)	/* discard (smoothed) future frame */
		  free_image (video->sfuture);
	       video->sfuture = sframe;	/* future <- current (smoothed) */
	       if (store_wfa)
		  copy_wfa (video->wfa_future, tmp_wfa);
	       if (video->frame)	/* discard current frame */
		  free_image (video->frame);
	       video->frame = NULL;
	       if (video->sframe)	/* discard current (smoothed) frame */
		  free_image (video->sframe);
	       video->sframe = NULL;
	       frame  = NULL;
	       sframe = NULL;
	    }
	    else
	    {
	       if (video->wfa->wfainfo->B_as_past_ref == YES)
	       {
		  if (video->past)	/* discard past frame */
		     free_image (video->past);
		  video->past  = video->frame; /* past <- current frame */
		  video->frame = NULL;
		  if (video->sframe)	/* discard current (smoothed) frame */
		     free_image (video->sframe);
		  video->sframe = NULL;
		  if (store_wfa)
		     copy_wfa (video->wfa_past, tmp_wfa);
	       }
	       else
	       {
		  if (video->frame)	/* discard current */
		     free_image (video->frame);
		  video->frame = NULL;
		  if (video->sframe)	/* discard current (smoothed) frame */
		     free_image (video->sframe);
		  video->sframe = NULL;
	       }
	    }
	 }
	 if (tmp_wfa)
	    free_wfa (tmp_wfa);
	 
	 current_frame_is_future_frame = NO;
	 /*
	  *  Second step: decode image
	  *  Optionally enlarge image if specified by option 'enlarge_factor'.
	  */
	 {
	    unsigned orig_width, orig_height;

	    stop_timer [0] = stop_timer [1] = stop_timer [2] = 0;
	 
	    enlarge_image (enlarge_factor, format,
			   (video->wfa->wfainfo->color
			    && format == FORMAT_4_2_0)
			   ? video->wfa->tree [video->wfa->tree [video->wfa->root_state][0]][0] : -1, video->wfa);

	    if (enlarge_factor > 0)
	    {
	       orig_width  = video->wfa->wfainfo->width  << enlarge_factor;
	       orig_height = video->wfa->wfainfo->height << enlarge_factor; 
	    }
	    else
	    { 
	       orig_width  = video->wfa->wfainfo->width  >> - enlarge_factor;
	       orig_height = video->wfa->wfainfo->height >> - enlarge_factor;
	       if (orig_width & 1)
		  orig_width++;
	       if (orig_height & 1)
		  orig_height++;
	    }
	 
	    frame = decode_image (orig_width, orig_height, format,
				  timer != NULL ? stop_timer : NULL,
				  video->wfa);
	    if (timer)
	    {
	       timer->preprocessing [video->wfa->frame_type] += stop_timer [0];
	       timer->decoder [video->wfa->frame_type]       += stop_timer [1];
	       timer->cleanup [video->wfa->frame_type]       += stop_timer [2];
	    }
	 }

	 /*
	  *  Third step: restore motion compensation
	  */
	 if (video->wfa->frame_type != I_FRAME)
	 {
	    prg_timer (&ptimer, START);
	    restore_mc (enlarge_factor, frame, video->past, video->future,
			video->wfa);
	    stop_timer [0] = prg_timer (&ptimer, STOP);
	    if (timer)
	       timer->motion [video->wfa->frame_type] += stop_timer [0];
	 }

	 /*
	  *  Fourth step: smooth image along partitioning borders
	  */
	 prg_timer (&ptimer, START);
	 if (smoothing < 0)	/* smoothing not changed by user */
	    smoothing = video->wfa->wfainfo->smoothing;
	 if (smoothing > 0 && smoothing <= 100)
	 {
	    sframe = clone_image (frame);
	    smooth_image (smoothing, video->wfa, sframe);
	 }
	 else
	    sframe = NULL;
	 
	 stop_timer [0] = prg_timer (&ptimer, STOP);
	 if (timer)
	    timer->smooth [video->wfa->frame_type] += stop_timer [0];

	 if (frame_number == video->display)
	 {
	    video->display++;
	    video->frame  = frame;
	    video->sframe = sframe;
	    frame         = NULL;
	    sframe        = NULL;
	 }
	 else if (frame_number > video->display)
	 {
	    video->future_display 	  = frame_number;
	    current_frame_is_future_frame = YES;
	 }
      
	 if (!store_wfa)
	    remove_states (video->wfa->basis_states, video->wfa);
      } while (!video->frame);

      if (!store_wfa)
	 video->wfa = NULL;
   }
   
   return video->sframe ? video->sframe : video->frame;
}
Пример #2
0
image_t *
decode_image (unsigned orig_width, unsigned orig_height, format_e format,
	      unsigned *dec_timer, const wfa_t *wfa)
/*
 *  Compute image which is represented by the given 'wfa'.
 *  'orig_width'x'orig_height' gives the resolution of the image at
 *  coding time. Use 4:2:0 subsampling or 4:4:4 'format' for color images.
 *  If 'dec_timer' is given, accumulate running time statistics. 
 *  
 *  Return value:
 *	pointer to decoded image
 *
 *  Side effects:
 *	'*dectimer' is changed if 'dectimer' != NULL.
 */
{
   unsigned   root_state [3];		/* root of bintree for each band */
   unsigned   width, height;		/* computed image size */
   image_t   *frame;			/* regenerated frame */
   word_t   **images;			/* pointer to array of pointers
					   to state images */
   u_word_t  *offsets;			/* pointer to array of state image
					   offsets */
   unsigned   max_level;		/* max. level of state with approx. */
   unsigned   state;
   clock_t    ptimer;

   prg_timer (&ptimer, START);

   /*
    *  Compute root of bintree for each color band
    */
   if (wfa->wfainfo->color)
   {
      root_state [Y]  = wfa->tree [wfa->tree [wfa->root_state][0]][0];
      root_state [Cb] = wfa->tree [wfa->tree [wfa->root_state][0]][1];
      root_state [Cr] = wfa->tree [wfa->tree [wfa->root_state][1]][0];
   }
   else
      root_state [GRAY] = wfa->root_state;

   /*
    *  Compute maximum level of a linear combination
    */
   for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++)
      if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0]))
	 max_level = max (max_level, wfa->level_of_state [state]);
   

   /*
    *  Allocate frame buffer for decoded image
    */
   compute_actual_size (format == FORMAT_4_2_0 ? root_state [Y] : MAXSTATES,
			&width, &height, wfa);
   width  = max (width, orig_width);
   height = max (height, orig_height);
   frame = alloc_image (width, height, wfa->wfainfo->color, format);
   
   /*
    *  Allocate buffers for intermediate state images
    */
   if (wfa->wfainfo->color)
   {
      wfa->level_of_state [wfa->root_state]               = 128;
      wfa->level_of_state [wfa->tree[wfa->root_state][0]] = 128;
      wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128;
   }
   alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, 
		       format, wfa);

   if (dec_timer)
      dec_timer [0] += prg_timer (&ptimer, STOP);

   /*
    *  Decode all state images, forming the complete image.
    */
   prg_timer (&ptimer, START);
   compute_state_images (max_level, images, offsets, wfa);
   if (dec_timer)
      dec_timer [1] += prg_timer (&ptimer, STOP);

   /*
    *  Cleanup buffers used for intermediate state images
    */
   prg_timer (&ptimer, START);
   free_state_images (max_level, frame->color, images, offsets, root_state, 0,
		      format, wfa);
   
   /*
    *  Crop decoded image if the image size differs.
    */
   if (orig_width != width || orig_height != height)
   {
      frame->height = orig_height;	
      frame->width  = orig_width;	
      if (orig_width != width)		
      {
	 color_e   band;		/* current color band */
	 word_t	  *src, *dst;		/* source and destination pointers */
	 unsigned  y;			/* current row */
	 
	 for (band  = first_band (frame->color);
	      band <= last_band (frame->color); band++)
	 {
	    src = dst = frame->pixels [band];
	    for (y = orig_height; y; y--)
	    {
	       memmove (dst, src, orig_width * sizeof (word_t));
	       dst += orig_width;
	       src += width;
	    }
	    if (format == FORMAT_4_2_0 && band == Y)
	    {
	       orig_width  >>= 1;
	       orig_height >>= 1;
	       width       >>= 1;
	    }
	 }
Пример #3
0
static void
video_decoder (const char *wfa_name, const char *image_name, bool_t panel,
	       bool_t double_resolution, int fps, fiasco_d_options_t *options)
{
   do
   {
      unsigned  	width, height, frames, n;
      fiasco_decoder_t *decoder_state;
      char     	       *filename;
      char     	       *basename;	/* basename of decoded frame */
      char     	       *suffix;		/* suffix of decoded frame */
      unsigned 		frame_time;
      
      if (!(decoder_state = fiasco_decoder_new (wfa_name, options)))
	 error (fiasco_get_error_message ());
   
      if (fps <= 0)			/* then use value of FIASCO file */ 
	 fps = fiasco_decoder_get_rate (decoder_state);
      frame_time = fps ? (1000 / fps) : (1000 / 25);

      if (!(width = fiasco_decoder_get_width (decoder_state)))
	  error (fiasco_get_error_message ());
      
      if (!(height = fiasco_decoder_get_height (decoder_state)))
	  error (fiasco_get_error_message ());

      if (!(frames = fiasco_decoder_get_length (decoder_state)))
	 error (fiasco_get_error_message ());
      
      get_output_template (image_name, wfa_name,
			   fiasco_decoder_is_color (decoder_state),
			   &basename, &suffix);

      filename = Calloc (strlen (basename) + strlen (suffix) + 2
			 + 10 + (int) (log10 (frames) + 1), sizeof (char));

      for (n = 0; n < frames; n++)
      {
	 clock_t fps_timer;		/* frames per second timer struct */
	 
	 prg_timer (&fps_timer, START);
	 
	 if (image_name)		/* just write frame to disk */
	 {
	    if (frames == 1)		/* just one image */
	    {
	       if (streq (image_name, "-"))
		  strcpy (filename, "-");
	       else
		  sprintf (filename, "%s.%s", basename, suffix);
	    }
	    else
	    {
	       fprintf (stderr, "Decoding frame %d to file `%s.%0*d.%s\n",
			n, basename, (int) (log10 (frames - 1) + 1),
			n, suffix);
	       sprintf (filename, "%s.%0*d.%s", basename,
			(int) (log10 (frames - 1) + 1), n, suffix);
	    }

	    if (!fiasco_decoder_write_frame (decoder_state, filename))
	       error (fiasco_get_error_message ());
	 }
      }
      free (filename);
      fiasco_decoder_delete (decoder_state);
   } while (panel);
}