:) 本文主要是記錄入門SDL的時候遇到的一些問題
侵刪
首先要感謝雷神 --
SDL簡介
- 一個用c語言寫的庫,主要用來操作視頻和音頻
- 是在將視頻和音頻解碼之后送往硬件的庫
大概梳理一下視頻播放的步驟
- 首先有概念要清楚,就是視頻文件中的聲音是送往音頻設(shè)備,視頻是送往屏幕,但是音頻設(shè)備能識別的就是原始的采樣數(shù)據(jù),而屏幕能識別的就是像素?cái)?shù)據(jù)。
- 平時我們遇到的視頻文件格式(MP4,F(xiàn)LV..)都是壓縮過后的數(shù)據(jù),壓縮過后空間占用更小。還有一點(diǎn)需要注意的是這些格式的文件都是同時又音頻和視頻數(shù)據(jù)
- 我們將視頻文件的數(shù)據(jù)解壓縮之后就能得到視頻數(shù)據(jù)和音頻數(shù)據(jù),這個過程稱為解碼。這里就會涉及到各種的編碼算法,常見的音頻編碼就是acc,常見的視頻編碼就是h264。也可以叫壓縮算法。 解碼之后我們就能達(dá)到acc編碼的音頻數(shù)據(jù),和h264編碼的視頻數(shù)據(jù),但是這些數(shù)據(jù)任然是壓縮的數(shù)據(jù)。
- 音頻的采樣數(shù)據(jù)格式是pcm,視頻的原始數(shù)據(jù)(未壓縮)是yuv,就是兩個文件格式,里面保存了音頻設(shè)備和視頻設(shè)備能夠直接使用的數(shù)據(jù)。把上面的acc和h264數(shù)據(jù)轉(zhuǎn)化成 pcm 和yuv數(shù)據(jù)之后就可以使用sdl庫將數(shù)據(jù)送往對應(yīng)的硬件設(shè)備。
SDL操作也比較固定(后面貼代碼)~
盜一張雷神的圖吧
- 代碼就這幾個步驟
- 首先初始化
- 創(chuàng)建一個window(其實(shí)就是一個視屏依附的窗口)
- 創(chuàng)建一個Renderer
- 最后是創(chuàng)建一個Texture(不斷的給Texture賦值就可以了)
- 這里還有一個概念就是 Window和Renderer是一一對應(yīng)的,但是Renderer和Texture不是一一對應(yīng)的哈。一個Renderer可以包含幾個Texture。也就是說一個Window可以分成幾塊來顯示。不同的快顯示不同的視屏。
說說Demo主要遇到的問題(IDE是vs2015)
- _imp__iob_func 和 _imp__fprintf 解決辦法
錯誤 LNK2019 無法解析的外部符號 __imp____iob_func,該符號在函數(shù) _ShowError 中被引用 PalyerDemo E:\vsprojects\PalyerDemo\PalyerDemo\SDL2main.lib(SDL_windows_main.obj) 1
錯誤 LNK2019 無法解析的外部符號 __imp__fprintf,該符號在函數(shù) _ShowError 中被引用 PalyerDemo E:\vsprojects\PalyerDemo\PalyerDemo\SDL2main.lib(SDL_windows_main.obj) 1
warning LNK4098: 默認(rèn)庫“MSVCRT”與其他庫的使用沖突;請使用 /NODEFAULTLIB:library 解決辦法
還有個奇葩問題msvcrt.dll 讀取位置 0x003BD000 時發(fā)生訪問沖突。這個主要是自己的代碼問題。(分配內(nèi)存的時候大小寫錯了)
Demo代碼吧(里面的yuv文件可以去雷神哪里下載)
#include "stdafx.h"
#include <stdio.h>
extern "C" {
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
#include "libswresample\swresample.h"
#include "libswscale\swscale.h"
FILE __iob_func[3] = { *stdin,*stdout,*stderr };
#include "SDL.h"
}
const int bpp = 12;
int screen_w = 640, screen_h = 360;
const int pixel_w = 640, pixel_h = 360;
unsigned char buffer[pixel_h * pixel_h * bpp / 8];
int main(int argc, char* argv[]) { //這里的main函數(shù)的參數(shù)主要是sdl里面也有一個main函數(shù)
//yuv到屏幕的過程
//SDL Simple DirectMedia Layer
if (SDL_Init(SDL_INIT_VIDEO)) {
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
SDL_Window *screen;
//SDL 2.0 Support for multiple windows
screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!screen) {
printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
return -1;
}
SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
Uint32 pixformat = 0;
//IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes)
pixformat = SDL_PIXELFORMAT_IYUV;
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);
FILE *fp = NULL;
fp = fopen("demo.yuv", "rb+");
if (fp == NULL) {
printf("cannot open this file\n");
return -1;
}
SDL_Rect sdlRect;
while (1) {
if (fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp) != pixel_w*pixel_h*bpp / 8) {
// Loop
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp);
}
SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);
sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = screen_w;
sdlRect.h = screen_h;
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
SDL_RenderPresent(sdlRenderer);
//Delay 40ms
SDL_Delay(40);
}
SDL_Quit();
return 0;
}
Nothing is certain in this life. The only thing i know for sure is that. I love you and my life. That is the only thing i know. have a good day