⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playh264.c

📁 decode the h264 video
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <time.h>#include <getopt.h>#include <SDL/SDL.h>#include "h264.h"#include "perf.h"#define USE_X86_ASM#define BitsPerPixel 16void help(char *arg) {  printf(    "Usage: %s [<options>] <streamfile.264>\n"    "<options> are:\n"    "  -h, -help        Show this help\n"    "  -z, -zoom <n>    Scale image by n\n"    "  -r, -fps <n>     Set maximum frame rate to n fps\n"    "      -fps 0       Wait for keypress after each frame\n"    "  -f, -frames <n>  Set maximum number of decoded frames\n"    "  -l, -loop        Enable looping\n"    "  -b, -bench       Benchmark mode\n"    "  -p, -perf        Enable performance counting\n"  ,arg);}static inline int clamp_and_scale(int i) {#ifdef USE_X86_ASM  asm(" \    sarl $20,  %%eax; \    cdq;              \    notl %%edx;       \    andl %%edx,%%eax; \    subl $256, %%eax; \    cdq;              \    notl %%edx;       \    orl  %%edx,%%eax; \    andl $255, %%eax; \  ":"=a"(i):"a"(i):"%edx");#else  i>>=20;  if(i<0)i=0; if(i>255)i=255;#endif  return i;}void showframe(SDL_Surface *screen, frame *f, int zoom) {  int i,x,y,Y,Cb=0,Cr=0,R,G,B;  unsigned char *pY,*pCb,*pCr;  unsigned char *line;#if (BitsPerPixel==32)#define DEST_TYPE unsigned int  DEST_TYPE cache;#define BytesPerPixel 4#endif#if (BitsPerPixel==24)#define DEST_TYPE unsigned char#define BytesPerPixel 3#endif#if (BitsPerPixel==15) || (BitsPerPixel==16)#define DEST_TYPE unsigned short  DEST_TYPE cache;#define BytesPerPixel 2#endif  DEST_TYPE *dest;  perf_enter("rendering");    SDL_LockSurface(screen);  line=screen->pixels;  for(y=0; y<f->Lheight; ++y) {    pY=&L_pixel(f,0,y);    pCb=&Cb_pixel(f,0,y>>1);    pCr=&Cr_pixel(f,0,y>>1);    dest=(DEST_TYPE *)line;    for(x=0; x<f->Lwidth; ++x) {      Y=*pY++;      if(!(x&1)) {        Cb=*pCb++;        Cr=*pCr++;      }      { int Y1,Pb,Pr;        Y1= (Y-16) *1225732;        Pb=(Cb-128)*1170;        Pr=(Cr-128)*1170;        R=clamp_and_scale(Y1        +1436*Pr);        G=clamp_and_scale(Y1- 352*Pb -731*Pr);        B=clamp_and_scale(Y1+1815*Pb);      }#if (BitsPerPixel==32)      cache=(R<<16)|(G<<8)|B;      for(i=zoom; i; --i)        *dest++=cache;#endif#if (BitsPerPixel==24)      for(i=zoom; i; --i) {        *dest++=B;        *dest++=G;        *dest++=R;      }#endif#if (BitsPerPixel==16)      cache=((R>>3)<<11)|((G>>2)<<5)|(B>>3);      for(i=zoom; i; --i)        *dest++=cache;#endif#if (BitsPerPixel==15)      cache=((R>>3)<<10)|((G>>3)<<5)|(B>>3);      for(i=zoom; i; --i)        *dest++=cache;#endif    }    dest=(DEST_TYPE *)line;    line+=screen->pitch;    for(i=zoom; i>1; --i) {      memcpy(line,dest,f->Lwidth*zoom*BytesPerPixel);      line+=screen->pitch;          }  }  SDL_UnlockSurface(screen);  SDL_UpdateRect(screen,0,0,0,0);}void do_bench(int maxframe) {  int frames=0;  struct timeval start,end;  double tdiff;    printf("Benchmarking ...\n");  gettimeofday(&start,NULL);  for(frames=0; h264_decode_frame(1); ++frames) {    if(maxframe && frames>=maxframe) break;    putchar('\r');    fflush(stdout);  }  gettimeofday(&end,NULL);  tdiff=end.tv_sec-start.tv_sec+0.000001*(end.tv_usec-start.tv_usec);  printf("%d frames decoded in %.1f seconds\n= %.1f ms/frame = %.1f fps\n",         frames,tdiff,1000.0*tdiff/frames,frames/tdiff);  h264_close();  perf_summarize();  exit(0);}int main(int argc, char *argv[]) {  SDL_Surface *screen;  SDL_Event ev;  int width,height,zoom=1,loop=0,delay=40,bench=0,perf=0,maxframe=0;  int pause=0,step=0,have_event;  int info;  int next_dts;  char *filename=NULL;  ///// Command Line Parameter Parsing ////////////////////////////////////////  const static struct option options[]={    {"help",   0, NULL, 'h'},    {"scale",  1, NULL, 'z'},    {"zoom",   1, NULL, 'z'},    {"xy",     1, NULL, 'z'},    {"fps",    1, NULL, 'r'},    {"frames", 1, NULL, 'f'},    {"loop",   0, NULL, 'l'},    {"bench",  0, NULL, 'b'},    {"perf",   0, NULL, 'p'},    {0, 0, 0, 0}  };  for(;;) {    int res,longidx;    res=getopt_long_only(argc,argv,"hz:r:f:lbp",options,&longidx);    if(res==-1) break;       switch(res) {      case 'h':        help(argv[0]);        return 0;      case 'l':        loop^=1;        break;      case 'b':        bench^=1;        break;      case 'p':        perf^=1;        break;      case 'z':        zoom=atoi(optarg);        if(zoom<1 || zoom>10) {          fprintf(stderr,"%s: invalid zoom value `%s'\n",argv[0],optarg);          return 1;        }        break;      case 'r':        delay=atoi(optarg);        if(delay<0 || delay>255) {          fprintf(stderr,"%s: invalid fps value `%s'\n",argv[0],optarg);          return 1;        }        if(delay) delay=1000/delay;        break;      case 'f':        maxframe=atoi(optarg);        if(delay<0) {          fprintf(stderr,"%s: invalid frame count value `%s'\n",argv[0],optarg);          return 1;        }        break;      case '?':        break;      case ':':      default:        return 1;    }  }  if(optind>=argc) {    fprintf(stderr,"%s: no filename specified\n",argv[0]);    return 1;  }  filename=argv[optind];  ///// Initialization ////////////////////////////////////////////////////////  info=h264_open(filename);  if(!info) return 1;  width=H264_WIDTH(info);  height=H264_HEIGHT(info);  if(perf) perf_enable();  if(bench) do_bench(maxframe);  printf("H.264 stream: %dx%d, zooming to %dx%d\n",         width,height,width*zoom,height*zoom);  if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)) {    fprintf(stderr,"%s: Error in SDL_Init: %s\n",argv[0],SDL_GetError());    return 1;  }  atexit(SDL_Quit);  SDL_WM_SetCaption(filename,"KeyJ's H.264 Viewer");  screen=SDL_SetVideoMode(width*zoom,height*zoom,BitsPerPixel,SDL_HWSURFACE);  if(!screen) {    fprintf(stderr,"%s: Error in SDL_SetVideoMode: %s\n",argv[0],SDL_GetError());    return 1;  }  ///// Main Loop /////////////////////////////////////////////////////////////  printf("Hint: ");  if(delay) printf("[Space] toggles pause; ");  printf("[Enter] advances to next frame\n");  pause=(!delay);  step=1;  next_dts=SDL_GetTicks();  for(;;) {    if((!pause) || step) {      frame *f;      printf("\r");      f=h264_decode_frame(1);      fflush(stdout);      if(maxframe && h264_frame_no()>=maxframe)        break;      if(f)        showframe(screen,f,zoom);      else if(loop) {        h264_rewind();        f=h264_decode_frame(1);        fflush(stdout);        if(!f) return 1;        showframe(screen,f,zoom);      } else        break;      next_dts+=delay;      if(step) step=0;    }    if(!pause) {      int wait=next_dts-SDL_GetTicks();      if(wait>0) SDL_Delay(wait);    }    if(pause) {      if(!SDL_WaitEvent(&ev))        break;      have_event=1;    } else      have_event=SDL_PollEvent(&ev);    if(have_event) {      if(ev.type==SDL_QUIT || (ev.type==SDL_KEYDOWN &&        (ev.key.keysym.sym==SDLK_ESCAPE || ev.key.keysym.sym==SDLK_q)))        break;      if(ev.type==SDL_KEYDOWN && ev.key.keysym.sym==SDLK_RETURN)        step=1;      if(delay && ev.type==SDL_KEYDOWN && ev.key.keysym.sym==SDLK_SPACE)        pause^=1;    }  }  printf("\nDecoding done.\n");  h264_close();  perf_summarize();  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -