天天看點

SDL2.0 播放YUV420p檔案

說明

ffmpeg提取YUV

ffmpeg -i xiongmao.flv -c:v rawvideo -pix_fmt yuv420p out.yuv      

ffplay播放YUV

ffplay -f rawvideo -video_size 1000x562 out.yu      

步驟

  1. 打開YUV檔案
  2. 循環讀取一幀圖檔的Y、U、V到記憶體。
  3. 将YUV資料交給紋理顯示

代碼

// SDL2_PLAY_YUV420.cpp : 定義控制台應用程式的入口點。
//

#include "stdafx.h"
#include "SDL.h"
#include "SDL_version.h"

#undef main


#define PATH_YUV420 "D:\\out.yuv"

#define width  1000
#define height 562


int main()
{

    //列印版本資訊
    SDL_version compiled;
    SDL_VERSION(&compiled);

    printf("SDL version %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch);


    //根據分辨率計算Y,U,V的長度
    int lenY = width * height;
    int lenU = width * height / 4;
    int lenV = width * height / 4;

    Uint8 *pYBuf = (Uint8 *)malloc(lenY);
    Uint8 *pUBuf = (Uint8 *)malloc(lenU);
    Uint8 *pVBuf = (Uint8 *)malloc(lenV);

    FILE *pFile = fopen(PATH_YUV420, "rb");
    if (pFile == NULL) {
        printf("open file failed\n");
        return -1;
    }

    //初始化SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
        return 1;

    SDL_Window *window = SDL_CreateWindow("SDL_WINDOW_TITLE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);   //渲染器
    SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, width, height);    //紋理是渲染的内容

    SDL_Rect rect;

    rect.x = 0;
    rect.y = 0;
    rect.w = width;
    rect.h = height;

    while (true) {

        if ((fread((void *)pYBuf, 1, lenY, pFile) == 0 || fread((void *)pUBuf, 1, lenU, pFile) == 0 || fread((void *)pVBuf, 1, lenV, pFile) == 0)) {

            printf("reach the end!\n");
            break;
        }


        SDL_UpdateYUVTexture(texture, &rect, pYBuf, width, pUBuf, width / 2, pVBuf, width / 2);

        //下面開始顯示紋理
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, &rect);
        SDL_RenderPresent(renderer);
        SDL_Delay(45);
    }

    fclose(pFile);

    free((void *)pYBuf);
    free((void *)pUBuf);
    free((void *)pVBuf);
    return 0;
}



#if 0

必須先知道YUV420的分辨率。根據分辨率才能知道一幀的Y、U、V分别長多是多少


#endif      

代碼下載下傳