diff options
author | jiguoliang <jiguoliang@localhost.localdomain> | 2011-01-04 17:03:14 +0800 |
---|---|---|
committer | jiguoliang <jiguoliang@localhost.localdomain> | 2011-01-04 17:03:14 +0800 |
commit | 858e396217601f1d356515356d79fbb6c057930d (patch) | |
tree | a67b4f0c44ef0aa08119b3bb2d17a8468d2b738a | |
parent | 1764bd178bd46dcc9756a180579ec5f3db688a93 (diff) | |
download | libva-858e396217601f1d356515356d79fbb6c057930d.tar.gz |
add the fool get frame function
-rw-r--r-- | va/va_fool.c | 16 | ||||
-rw-r--r-- | va/va_fool.h | 2 | ||||
-rw-r--r-- | va/va_getframe.c | 165 | ||||
-rw-r--r-- | va/va_getframe.h | 25 |
4 files changed, 205 insertions, 3 deletions
diff --git a/va/va_fool.c b/va/va_fool.c index 519304d..3df179e 100644 --- a/va/va_fool.c +++ b/va/va_fool.c @@ -26,6 +26,7 @@ #include "va.h" #include "va_backend.h" #include "va_trace.h" +#include "va_fool.h" #include <assert.h> #include <stdarg.h> @@ -40,6 +41,7 @@ #include <time.h> #include "va_fool_264.h" +#include "va_getframe.c" /* @@ -64,7 +66,10 @@ static int fool_decode = 0; static int fool_encode = 0; int fool_postp = 0; +static char clip[1024]; +static char *frame_buf; +#define MAX_FRAME 16 #define FOOL_CONTEXT_MAX 4 /* per context settings */ static struct _fool_context { @@ -165,6 +170,8 @@ void va_FoolInit(VADisplay dpy) if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) { FILE *tmp = fopen(env_value, "r"); + memset(clip,0,sizeof(char)*1024); + memcpy(clip,env_value,sizeof(env_value)); if (tmp) fool_context[fool_index].fool_fp_codedclip = tmp; @@ -395,7 +402,6 @@ VAStatus va_FoolCreateBuffer ( return 0; /* let driver go ... */ } - VAStatus va_FoolMapBuffer ( VADisplay dpy, VABufferID buf_id, /* in */ @@ -424,12 +430,17 @@ VAStatus va_FoolMapBuffer ( /* expect APP to MapBuffer when get the the coded data */ if (*pbuf && (buf_idx == VAEncCodedBufferType)) { /* it is coded buffer */ /* should read from a clip, here we use the hardcoded h264_720p_nal */ +#if 0 memcpy(*pbuf, &h264_720p_nal[h264_720p_nal_idx], sizeof(VACodedBufferSegment)); h264_720p_nal_idx++; if (h264_720p_nal_idx == H264_720P_NAL_NUMBER) h264_720p_nal_idx = 0; /* reset to 0 */ +#endif + frame_buf=malloc(MAX_FRAME*SLICE_NUM*NAL_BUF_SIZE*sizeof(char)); + memset(frame_buf,0,SLICE_NUM*NAL_BUF_SIZE); + va_FoolGetFrame( clip , 16, frame_buf); + *pbuf=frame_buf; } - return 1; /* don't call into driver */ } @@ -521,6 +532,7 @@ VAStatus va_FoolUnmapBuffer ( DPY2INDEX(dpy); if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */ + free(frame_buf); return 1; } return 0; diff --git a/va/va_fool.h b/va/va_fool.h index a3d0a92..1e10523 100644 --- a/va/va_fool.h +++ b/va/va_fool.h @@ -25,7 +25,7 @@ #ifndef VA_FOOL_H #define VA_FOOL_H - +#include "va_getframe.h" void va_FoolInit(VADisplay dpy); int va_FoolEnd(VADisplay dpy); diff --git a/va/va_getframe.c b/va/va_getframe.c new file mode 100644 index 0000000..17b663d --- /dev/null +++ b/va/va_getframe.c @@ -0,0 +1,165 @@ +#define SLICE_NUM 4 + +static unsigned char nal_buf[NAL_BUF_SIZE]; +static unsigned char ring_buf[RING_BUF_SIZE]; +static int input_remain; +static int ring_pos; +static int nal_pos; +static int nal_bit; +static FILE *input_fd=NULL; + +#define RING_MOD ((RING_BUF_SIZE)-1) +#define HALF_RING ((RING_BUF_SIZE)/2) + +#define gnn_advance() do { \ + ring_pos=(ring_pos+1)&RING_MOD; \ + --input_remain; \ + if(ring_pos==0) input_read(&ring_buf[HALF_RING],HALF_RING); \ + if(ring_pos==HALF_RING) input_read(&ring_buf[0],HALF_RING); \ +} while(0) + +#define gnn_add_segment(end) do { \ + int size=end-segment_start; \ + if(size>0) { \ + memcpy(&nal_buf[nalu_size],&ring_buf[segment_start],size); \ + nalu_size+=size; \ + } \ + segment_start=end&RING_MOD; \ +} while(0) + +static int input_get_bits(int bit_count) { + int res=0; + register unsigned int x= + (nal_buf[nal_pos]<<24)| + (nal_buf[nal_pos+1]<<16)| + (nal_buf[nal_pos+2]<<8)| + nal_buf[nal_pos+3]; + res=(x>>(32-bit_count-nal_bit))&((1<<bit_count)-1); + nal_bit+=bit_count; + nal_pos+=nal_bit>>3; + nal_bit&=7; + return res; +} + +int input_get_one_bit() { + int res=(nal_buf[nal_pos]>>(7-nal_bit))&1; + if(++nal_bit>7) { + ++nal_pos; + nal_bit=0; + } + return res; +} + +int get_unsigned_exp_golomb() { + int exp; + for(exp=0; !input_get_one_bit(); ++exp); + if(exp) return (1<<exp)-1+input_get_bits(exp); + else return 0; +} + +void decode_slice_header(slice_header *sh ) { + memset((void*)sh,0,sizeof(slice_header)); + sh->first_mb_in_slice =get_unsigned_exp_golomb(); +} + +static int get_next_nal_unit(nal_unit *nalu) { + int i,segment_start; + int nalu_size=0; + int NumBytesInRbsp=0; + + // search for the next NALU start + // here is the sync that the start of the NALU is 0x00000001 + for(;;) { + if(input_remain<=4) return 0; + + if((!ring_buf[ring_pos]) && + (!ring_buf[(ring_pos+1)&RING_MOD]) && + (!ring_buf[(ring_pos+2)&RING_MOD]) && + ( ring_buf[(ring_pos+3)&RING_MOD]==1)) + break; + gnn_advance(); + } + for(i=0; i<4; ++i) gnn_advance(); + + // add bytes to the NALU until the end is found + segment_start=ring_pos; + while(input_remain) { + if((!ring_buf[ring_pos]) && + (!ring_buf[(ring_pos+1)&RING_MOD]) && + (!ring_buf[(ring_pos+2)&RING_MOD])) + break; + ring_pos=(ring_pos+1)&RING_MOD; + --input_remain; + if(ring_pos==0) { + gnn_add_segment(RING_BUF_SIZE); + input_read(&ring_buf[HALF_RING],HALF_RING); + } + if(ring_pos==HALF_RING) { + gnn_add_segment(HALF_RING); + input_read(&ring_buf[0],HALF_RING); + } + } + + gnn_add_segment(ring_pos); + if(!nalu_size) + fclose(input_fd); + + // read the NAL unit + nal_pos=0; nal_bit=0; + nalu->forbidden_zero_bit=input_get_bits(1); + nalu->nal_ref_idc=input_get_bits(2); + nalu->nal_unit_type=input_get_bits(5); + nalu->last_rbsp_byte=&nal_buf[nalu_size-1]; + nalu->NumBytesInNALunit=nalu_size; + return 1; +} + +static int input_open(char *filename) { + if(input_fd) { + fprintf(stderr,"input_open: file already opened\n"); + return 0; + } + input_fd=fopen(filename,"rb"); + if(!input_fd) { + perror("input_open: cannot open file"); + return 0; + } + input_remain=0; + input_read(ring_buf,RING_BUF_SIZE); + ring_pos=0; + + return 1; +} + +static void input_read(unsigned char *dest, int size) { + int count=fread(dest,1,size,input_fd); + input_remain+=count; +} + +//get the frame address +int va_FoolGetFrame(char *filename, int maxframe, char *frame_buf) { + int i, size_info, frame_pos=0; + int frame_no=0; + static slice_header sh; + static nal_unit nalu; + + input_open(filename); + while(get_next_nal_unit(&nalu)) + { + if(nalu.nal_unit_type==1 || nalu.nal_unit_type==5) { + decode_slice_header(&sh); + if(0==sh.first_mb_in_slice) + { + ++frame_no; + frame_pos=0; + } + if(maxframe && frame_no>maxframe) + break; + memcpy(frame_buf+frame_pos, nal_buf+1, sizeof(char)*(nalu.NumBytesInNALunit-1)); + frame_pos += nalu.NumBytesInNALunit; + } + } + fclose(input_fd); + + return 1; +} diff --git a/va/va_getframe.h b/va/va_getframe.h new file mode 100644 index 0000000..44e5009 --- /dev/null +++ b/va/va_getframe.h @@ -0,0 +1,25 @@ +#ifndef __NAL_H__ +#define __NAL_H__ + +#define NAL_BUF_SIZE 65536 // maximum NAL unit size +#define RING_BUF_SIZE 8192 // input ring buffer size, MUST be a power of two! + +typedef struct _nal_unit { + int NumBytesInNALunit; + int forbidden_zero_bit; + int nal_ref_idc; + int nal_unit_type; + unsigned char *last_rbsp_byte; +} nal_unit; + typedef struct _slice_header { + int first_mb_in_slice; +} slice_header; + +static int get_next_nal_unit(nal_unit *nalu); +static int get_unsigned_exp_golomb(); +static void decode_slice_header(slice_header *sh); +static int input_open(char *filename); +static void input_read(unsigned char *dest, int size); +static int input_get_bits(int bit_count); +int va_FoolGetFrame(char *filename, int maxframe, char *frame_buf); +#endif /*__NAL_H__*/ |