www.pudn.com > p264decoder.zip > p264decoder.c


/*****************************************************************************
 * p264: h264 encoder/decoder testing program.
 *****************************************************************************
 * Copyright (C) 2003 Laurent Aimar
 * $Id: p264.c,v 1.1 2004/06/03 19:24:12 fenrir Exp $
 *
 * Authors: Laurent Aimar 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/ 
//lsp???

#include 
#include 
#include 

#include 

#include 
#define _GNU_SOURCE
#include 

#ifdef _MSC_VER
#include      /* _setmode() */
#include   /* _O_BINARY */
#endif

#include "core/core.h"
#include "p264.h"

#ifndef _MSC_VER
#include "config.h"
#endif


#define DATA_MAX 3000000
uint8_t data[DATA_MAX];

typedef void *hnd_t;

/* Ctrl-C handler */
static int     b_ctrl_c = 0;
static int     b_exit_on_ctrl_c = 0;
static void    SigIntHandler( int a )
{
    if( b_exit_on_ctrl_c )
        exit(0);
    b_ctrl_c = 1;
}

 
static void Help( p264_param_t *defaults ); 
static int  Decode( p264_param_t  *param,int argc, char **argv);
/****************************************************************************
 * main:
 ****************************************************************************/
int main( int argc, char **argv )
{
    p264_param_t param;

#ifdef _MSC_VER
    _setmode(_fileno(stdin), _O_BINARY);    /* thanks to Marcos Morais  */
    _setmode(_fileno(stdout), _O_BINARY);
#endif

    p264_param_default( ¶m );

    /* Control-C handler */
    signal( SIGINT, SigIntHandler );

    //lsp decoder
    //command line example: p264 -d test.264 [rec.yuv] [ref.yuv]
    if (argc>=3 && 0==strcmp(argv[1],"-d")) 
    { 
      return Decode(¶m, argc, argv); 
    } 
    else 
    { 
      Help(¶m); 
      return -1; 
    }
}

static const char * const overscan_str[] = { "undef", "show", "crop", NULL };
static const char * const vidformat_str[] = { "component", "pal", "ntsc", "secam", "mac", "undef", NULL };
static const char * const fullrange_str[] = { "off", "on", NULL };
static const char * const colorprim_str[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", NULL };
static const char * const transfer_str[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", NULL };
static const char * const colmatrix_str[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", NULL };

static char const *strtable_lookup( const char * const table[], int index )
{
    int i = 0; while( table[i] ) i++;
    return ( ( index >= 0 && index < i ) ? table[ index ] : "???" );
}

/*****************************************************************************
 * Help:
 *****************************************************************************/
static void Help( p264_param_t *defaults )
{ 
    fprintf( stderr, 
             "p264 Decoder:\n" 
             "\n" 
             "      -d  [recon.yuv] [origin.yuv]" 
             "\n" 
             );
}

/*****************************************************************************
 * Decode:
 *****************************************************************************/ 
//write frame yuv 
void write_frame(p264_picture_t *pic,FILE *fp_rec) 
{ 
  int	i; 
  uint8_t* p; 
 
  if(NULL==fp_rec) 
    return; 
 
  //y 
  p=pic->img.plane[0]; 
  for (i=0; ii_height; i++) 
  { 
    fwrite(p,1,pic->i_width,fp_rec); 
    p+=pic->img.i_stride[0]; 
  } 
  //u 
  p=pic->img.plane[1]; 
  for (i=0; i< pic->i_height>>1; i++) 
  { 
    fwrite(p,1,pic->i_width>>1,fp_rec); 
    p+=pic->img.i_stride[1]; 
  } 
  //v 
  p=pic->img.plane[2]; 
  for (i=0; i< pic->i_height>>1; i++) 
  { 
    fwrite(p,1,pic->i_width>>1,fp_rec); 
    p+=pic->img.i_stride[2]; 
  } 
 
} 
 
enum 
{ 
  PARSE_STATE_INIT=0, 
  PARSE_STATE_A, 
  PARSE_STATE_B 
}; 
static int  Decode( p264_param_t  *param,int argc, char **argv) 
{ 
  p264_t *h; 
  FILE *fp_h264=NULL, *fp_rec=NULL, *fp_ref=NULL; 
  int i_data_size, i_cur, i_nal_start; //buffer correlative 
  int b_eof_h264=0; 
  int i_read; 
  int b_need_buffer=0; 
  int i_parse_state, i_start_code_size; //nal extraction correlative 
  int b_find_nal; 
  int b_decode_finish; 
  p264_nal_t nal; 
  p264_picture_t *p_pic_recon; //the recon picture 
  int64_t i_start, i_end; //decode speed compute 
  int i_frames=0; 
 
  //[1] init 
  fprintf(stderr,"decoding start...\n"); 
  //malloc 
  nal.p_payload = malloc( DATA_MAX ); 
  //open h264 stream file 
  fp_h264=fopen(argv[2],"rb"); 
  if (NULL==fp_h264) 
  { 
    fprintf(stderr, "open h264 stream file: %s failed\n",argv[2]); 
    return -1; 
  } 
  //open rec file 
  if (argc>=4) 
  { 
    fp_rec=fopen(argv[3],"wb"); 
  } 
  //open ref file 
  if (argc==5) 
  { 
    fp_ref=fopen(argv[4],"rb"); 
  } 
 
 
  if( ( h = p264_decoder_open( param ) ) == NULL ) 
  { 
    fprintf( stderr, "p264_decoder_open failed\n" ); 
    return -1; 
  } 
 
  i_start = p264_mdate(); 
 
  //confirm the first start code 
  i_read=fread(&data[0],1,DATA_MAX,fp_h264); 
  if(i_read < 4) 
  { 
    fprintf(stderr,"the h264 stream file is too small, even can't include the first start code\n"); 
    return -1; 
  } 
  i_data_size=i_read; 
  if(data[0]!=0x00 || data[1]!=0x00 || data[2]!=0x00 || data[3]!=0x01 ) 
  { 
    fprintf(stderr,"confirm the first start code failed\n"); 
    return -1; 
  } 
  i_cur=4; 
  i_nal_start=4; 
  b_need_buffer=0; 
  b_decode_finish=0; 
  //[2] main loop 
  while (!b_ctrl_c && !b_decode_finish) 
  { 
    //[2.1] fill buffer 
    if (b_need_buffer) 
    { 
      //transfer the partly read nal data to the top of the buffer 
      //note: here, i_data_size must equal with i_cur 
      i_data_size=i_cur-i_nal_start;  
      memmove(&data[0],&data[i_nal_start],i_data_size); //overlap is possible 
      i_nal_start=0; 
      i_cur=i_data_size; 
 
      //read more data 
      i_read=fread(&data[i_data_size],1,DATA_MAX-i_data_size,fp_h264); 
      if (i_read<=0) 
      { 
        b_eof_h264=1; 
      } 
      else 
      { 
        i_data_size+=i_read; 
      } 
 
      b_need_buffer=0;//!! 
    } 
    else 
    { 
      i_parse_state=PARSE_STATE_INIT; 
    } 
 
    //[2.2] extract a nal 
    b_find_nal=0; 
    while (i_cur=i_data_size) 
    { 
      if (b_eof_h264) 
      { 
        i_start_code_size=0;//for it is the last nal //lsp!!!! 
        b_decode_finish=1; 
      } 
      else 
      { 
        b_need_buffer=1; //the buffer is extractly used over 
      } 
    } 
    
    //[2.3] decode the nal (find nal type...) 
    p264_nal_decode( &nal, &data[i_nal_start], i_cur-i_nal_start-i_start_code_size ); 
 
    //update the data index 
    i_nal_start=i_cur; 
 
 
    //lspdebug 
    //printf("nal size:%d, type: %d\n",nal.i_payload,nal.i_type); 
 
    //[2.4] decode the nal content 
    p264_decoder_decode( h, &p_pic_recon, &nal ); 
    if(NULL!=p_pic_recon) 
    { 
      i_frames++; 
      if(NULL!=fp_rec) 
      { 
        write_frame(p_pic_recon, fp_rec); 
      } 
    } 
 
    //if(h->sh.i_frame_num==4) //lspdebug 
    //{ 
    //  break; 
    //} 
 
  }//end of while (!b_ctrl_c) 
 
  i_end = p264_mdate();

  if( i_frames > 0 )
  {
    double fps = (double)i_frames * (double)1000000 /
      (double)( i_end - i_start );

    fprintf(stderr, "decoded total %d frames \n", i_frames);
    fprintf(stderr, "decoding speed: %.2f fps\n", fps);
  }
 
  //[3] free and close 
   p264_decoder_close( h ); 
 
   //close file 
   fclose(fp_h264); 
   if (NULL!=fp_rec) 
   { 
     fclose(fp_rec); 
   } 
   if (NULL!=fp_ref) 
   { 
     fclose(fp_ref); 
   } 
 
   free( nal.p_payload ); 
 
   return 0; 
 
}