zoukankan      html  css  js  c++  java
  • yuv播放器

    用sdl写个播放器, 播放yuv 

    发现播放yuv的应用还很广,主要是测试时用到

    基于sdl, 现在出了sdl2.0, 暂用1.2的, 这个比较熟悉


    todo:

    1. 支持size的改变

    2. 读取yuv的信息

    3. 截取其中的一帧

    4. 支持yuv nv12 yuv444, yuv422 , rgb24等主流

    5. 跨平台


    先贴个1.0(暂且这么叫吧)

    #include<stdio.h>
    #include<unistd.h>
    #include<SDL/SDL.h>
    
    FILE                   *fp;
    SDL_Surface            *screen;
    const int width  = 1920;
    const int height = 1080;
    
    void QuitSdl(SDL_Event event);
    SDL_Surface* SDL_ScaleSurface(SDL_Surface *Surface, Uint16 Width, Uint16 Height);
    void ApplySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination );
    int ThreadCallBack(void *para);
    
    
    int main(int argc, char **argv)
    {
        const SDL_VideoInfo    *monitor;
        SDL_Surface            *background;
        SDL_Surface            *ground;
        SDL_Event              event;
        SDL_Thread             *thread = NULL;
    
        void                   *param;
        
        if(SDL_Init(SDL_INIT_VIDEO))
        {
            printf("Coundnot init SDL
    ");
            exit(1);
        }
        
        monitor    = SDL_GetVideoInfo();
        screen     = SDL_SetVideoMode(width, height, 24, SDL_SWSURFACE);    
        background = SDL_LoadBMP("background.bmp");
        ground     = SDL_ScaleSurface(background, width, height); 
        SDL_BlitSurface(ground, NULL, screen, NULL);
        ApplySurface(0, 0, ground, screen);
        SDL_Flip(screen);
    
        fp = fopen("a.yuv","r");
        if(NULL == fp)
        {
            printf("open file error
    ");
            exit(1);
        }
    
        thread  = SDL_CreateThread(ThreadCallBack, (void*)¶m);
        if(NULL == thread)
        {
            printf("Thread Cread error
    ");
            exit(1);
        }
    
        while(1)
        {
            SDL_WaitEvent(&event);
            QuitSdl(event);
        }
        return 0;
    }
    
    
    void ApplySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
    {
    	//Temporary rectangle to hold the offsets
    	SDL_Rect offset;
    	//Get the offsets
    	offset.x = x;
    	offset.y = y;
    	SDL_BlitSurface( source, NULL, destination, &offset );
    }
    
    void QuitSdl(SDL_Event event)
    {
        switch(event.type)
        {
            case SDL_QUIT:
                SDL_Quit();
                break;
        }
        return ;
    }
    
    
    Uint32 ReadPixel(SDL_Surface *surface, int x, int y)
    {
    	int bpp = surface->format->BytesPerPixel;
    	/* Here p is the address to the pixel we want to retrieve */
    	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    
    	switch(bpp) {
    		case 1:
    			return *p;
    			break;
    
    		case 2:
    			return *(Uint16 *)p;
    			break;
    
    		case 3:
    			if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
    				return p[0] << 16 | p[1] << 8 | p[2];
    			else
    				return p[0] | p[1] << 8 | p[2] << 16;
    			break;
    
    		case 4:
    			return *(Uint32 *)p;
    			break;
    
    		default:
    			return 0;       /* shouldn't happen, but avoids warnings */
    	}
    }
    
    void DrawPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
    {
    	int bpp = surface->format->BytesPerPixel;
    	/* Here p is the address to the pixel we want to set */
    	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    
    	switch(bpp) {
    		case 1:
    			*p = pixel;
    			break;
    
    		case 2:
    			*(Uint16 *)p = pixel;
    			break;
    
    		case 3:
    			if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    				p[0] = (pixel >> 16) & 0xff;
    				p[1] = (pixel >> 8) & 0xff;
    				p[2] = pixel & 0xff;
    			} else {
    				p[0] = pixel & 0xff;
    				p[1] = (pixel >> 8) & 0xff;
    				p[2] = (pixel >> 16) & 0xff;
    			}
    			break;
    
    		case 4:
    			*(Uint32 *)p = pixel;
    			break;
    	}
    }
    
    SDL_Surface* SDL_ScaleSurface(SDL_Surface *Surface, Uint16 Width, Uint16 Height)
    {
              SDL_Surface *_ret = SDL_CreateRGBSurface(Surface->flags, Width, Height, Surface->format->BitsPerPixel,
                                                              Surface->format->Rmask, Surface->format->Gmask, Surface->format->Bmask, Surface->format->Amask);
    
             double    _stretch_factor_x = ((double)Width / (double)(Surface->w)),
                _stretch_factor_y = ((double)(Height) / (double)(Surface->h));
    
            for(Sint32 y = 0; y < Surface->h; y++) //Run across all Y pixels.
                for(Sint32 x = 0; x < Surface->w; x++) //Run across all X pixels.
                    for(Sint32 o_y = 0; o_y < _stretch_factor_y; ++o_y) //Draw _stretch_factor_y pixels for each Y pixel.
                        for(Sint32 o_x = 0; o_x < _stretch_factor_x; ++o_x) //Draw _stretch_factor_x pixels for each X pixel.
                            DrawPixel(_ret, (Sint32)(_stretch_factor_x * x) + o_x, 
                                                             (Sint32)(_stretch_factor_y * y) + o_y, ReadPixel(Surface, x, y));
    
            return _ret;
    }
    
    int ThreadCallBack(void *para)
    {
        unsigned char buf[width*height*3/2];
        unsigned char *py, *pu, *pv;
        int  len, pyLen, puLen, pvLen;
        SDL_Overlay *bmp;
        SDL_Rect    rect;
        bmp  = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);
    //    buf = (unsigned char*)malloc(sizeof(unsigned char)*1920*1080*3/2);
        
        py  = buf;
        pu  = buf + width*height;
        pv  = buf + width*height*5/4;
    
        pyLen = width*height;
        puLen = pvLen = width*height/4;
        rect.x = 0;
        rect.y = 0;
        rect.w = width;
        rect.h = height;
        
        while(1)
        {
            len = fread(buf, 1, width*height*3/2, fp);
            printf("len=%d
    ",len);
            SDL_LockYUVOverlay(bmp);
    
            bmp->pixels[0] = py;
            bmp->pixels[2] = pu;
            bmp->pixels[1] = pv;
            
            bmp->pitches[0] = pyLen;
            bmp->pitches[2] = puLen;
            bmp->pitches[1] = pvLen;
    
            SDL_UnlockYUVOverlay(bmp);
    
            SDL_DisplayYUVOverlay(bmp, &rect);
            sleep(1);
        }
        return 0;
    }
    

    里面有两个文件,一个yuv, 一个bmp

    每天早上叫醒你的不是闹钟,而是心中的梦~
  • 相关阅读:
    C语言头文件stdarg.h(cstdarg)
    C语言头文件ctype.h(cctype)
    内存数库库种类
    C#设计模式单件模式(Singleton Pattern)
    vs2005快捷键,vs2008通用
    移动MYSQL数据库经常遇到乱码的问题
    ie6 ie7 ie8 共存以及Firefox浏览器CSS兼容写法
    用正则表达式替换a标记href值
    IE6 PNG透明终极解决方案(打造W3CfunsIE6PNG最强帖)
    IE的hack
  • 原文地址:https://www.cnblogs.com/vintion/p/4116949.html
Copyright © 2011-2022 走看看