• 一个简单的使用SDL播放YUV文件的示例


    SDL(Simple DirectMedia Layer)是个好东西!

    要想开发一个自己的跨平台的媒体播放器(如ffplay等),它就大有武之地啦。

    SDL的入门介绍有很多,比如中文的有“龙飞”的洋洋洒洒一个系列:

    http://www.cppblog.com/lf426/archive/2008/01/30/42161.aspx

    当然,官方的教程是很有用:

    http://lazyfoo.net/SDL_tutorials/index.php

    官方的教程讲了SDL的各个方面,但是并没有讲播放器的具体设计。而ffmpeg的

    教程(http://dranger.com/ffmpeg/tutorial01.html)夹杂着一堆的ffmpeg专用的代码,

    搞得想单看的人很混乱,所以我结合了这两个教程,写了一个很简单的示例程序。


    #include"SDL-1.2.14\include\SDL.h"
    #include <string>
    #include <stdlib.h>

    /* The pre-defined attributes of the screen */
    // CIF
    const int SCREEN_WIDTH  = 352;
    const int SCREEN_HEIGHT = 288;
    const int SCREEN_BPP    = 8;

    typedef struct yuv_pic
    {
      char* pv_data[4];
      int   v_linesize[4]; //number of bytes per line
    } s_picture;



    int main( int argc, char* args[])
    {
      FILE* pf_yuv;
      SDL_Surface* ps_screen;
      SDL_Overlay* ps_bmp;
      SDL_Rect     s_rect;

      char*        pv_frame = NULL;
      int          v_pic_size = 0, v_frame_size = 0;
      s_picture    s_yuv_pic;

      /* Init SDL */
      if( SDL_Init(SDL_INIT_EVERYTHING) == -1)
      {
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
        exit(1);
      }

      /* Set up the screen */
      ps_screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_SWSURFACE);
      if( !ps_screen )
      {
        fprintf(stderr, "SDL: could not set video mode -exiting\n");
        exit(1);
      }

      /* Set the window caption */
      SDL_WM_SetCaption( "YUV Window", NULL);

      /* Create a YUV overlay */
      ps_bmp = SDL_CreateYUVOverlay(SCREEN_WIDTH, SCREEN_HEIGHT, SDL_YV12_OVERLAY,
        ps_screen);

      /* Open the YUV file */
      if( (pf_yuv = fopen("coastguard_cif.yuv", "r")) == NULL )
      {
        fprintf(stderr, "SYS: could not open file %s\n", "akiyo_cif.yuv");
        exit(2);
      }

      v_frame_size = (SCREEN_WIDTH * SCREEN_HEIGHT);
      v_pic_size   = ((v_frame_size * 3) / 2);
      if( (pv_frame = (char*)calloc(v_pic_size, 1)) == NULL )
      {
        fprintf(stderr, "SYS: could not allocate mem space\n");
        exit(2);
      }

      s_yuv_pic.pv_data[0] = pv_frame;  //Y
      s_yuv_pic.pv_data[1] = (char*)(pv_frame + v_frame_size);
      s_yuv_pic.pv_data[2] = (char*)(pv_frame + v_frame_size + v_frame_size/4);
      s_yuv_pic.v_linesize[0] = SCREEN_WIDTH;
      s_yuv_pic.v_linesize[1] = (SCREEN_WIDTH/2);
      s_yuv_pic.v_linesize[2] = (SCREEN_WIDTH/2);

      /* Apply the image to the screen */
      ps_bmp->pixels[0] = (unsigned char*)(s_yuv_pic.pv_data[0]);
      ps_bmp->pixels[2] = (unsigned char*)(s_yuv_pic.pv_data[1]);
      ps_bmp->pixels[1] = (unsigned char*)(s_yuv_pic.pv_data[2]);

      ps_bmp->pitches[0] = s_yuv_pic.v_linesize[0];
      ps_bmp->pitches[2] = s_yuv_pic.v_linesize[1];
      ps_bmp->pitches[1] = s_yuv_pic.v_linesize[2];

      /* Update the screen */
      s_rect.x = 0;
      s_rect.y = 0;
      s_rect.w = SCREEN_WIDTH+8;
      s_rect.h = SCREEN_HEIGHT+8;

      /* Load YUV frames */
      int i = 0, ret=0;
      while( !(ret = fread(pv_frame, v_pic_size, 1, pf_yuv)) )
      {
        i++;
        fprintf(stderr, "%dth frame's ret = %d\n", i, ret);

        fseek(pf_yuv, v_pic_size*i, SEEK_SET);
       
        SDL_LockYUVOverlay(ps_bmp);

        SDL_DisplayYUVOverlay(ps_bmp, &s_rect);

        SDL_UnlockYUVOverlay(ps_bmp);
     
        SDL_Delay( 40 );
      }


      /* Free the surfaces */
      fclose(pf_yuv);
      free(pv_frame);

      /* Quit SDL */
      SDL_Quit();

      return 0;
    }




  • 相关阅读:
    利用@media screen实现网页布局的自适应
    js判断手机的左右滑动
    文档流
    对文本段落操作的一些细节
    简易菜单的制作
    jQuery Scroll Follow
    node 监听接口
    浏览器通知
    webSocket
    前端学习路线
  • 原文地址:https://www.cnblogs.com/neoyan/p/2837990.html
Copyright © 2020-2023  润新知