亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

演示基于SDL2.0+FFmpeg的播放器

系統(tǒng) 1626 0

SDL是一個(gè)跨平臺(tái)的渲染組件,眼下已經(jīng)推出到2.0.3版本號(hào),支持Win/Linux/OSX/Android。網(wǎng)上非常多介紹大多是基于SDL1.2版本號(hào)的,與2.0版本號(hào)有一定的區(qū)別,本文演示怎樣用SDL2.0版本號(hào)播放視頻(僅視頻)。

SDL下載站點(diǎn):http://libsdl.org

參考網(wǎng)址:http://blog.csdn.net/dawdo222/article/details/8692834

上代碼:

      // 演示怎樣用SDL2進(jìn)行播放
//可參考http://blog.csdn.net/dawdo222/article/details/8692834

#include "stdafx.h"
#include <stdio.h>  
#include <tchar.h>  
#include <io.h>  
#include <direct.h> 
#include <windows.h>

extern "C"  
{  
    // ffmpeg  
#include "libavcodec/avcodec.h"  
#include "libavformat/avformat.h"  
#include "libswscale/swscale.h"  
    // SDL  
#include "SDL203include/SDL.h"  
#include "SDL203include/SDL_thread.h"  
};  
  
#pragma comment(lib,"../lib/avutil.lib")  
#pragma comment(lib,"../lib/avcodec.lib")  
#pragma comment(lib,"../lib/avformat.lib")  
#pragma comment(lib,"../lib/swscale.lib")  
#pragma comment(lib,"../lib/sdl2.lib")  


//把參數(shù)轉(zhuǎn)換為utf8
void prepare_app_arguments2(int *argc_ptr, char ***argv_ptr)
{
	int i, nSize, newSize, buffsize;
	char *argv; 
	char **argv2;
	wchar_t* lpWideCharStr;
	char* buf;
	char** win32_argv_utf8 = NULL;
	argv2 = *argv_ptr;

	
	buffsize = 0;
	/* determine the UTF-8 buffer size (including NULL-termination symbols) */
    for (i = 0; i < *argc_ptr; i++)
	{
		argv = argv2[i];
		nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(char), NULL, 0);
		lpWideCharStr = (wchar_t*)av_mallocz( (nSize+1) * sizeof(wchar_t));
		MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(wchar_t), lpWideCharStr, nSize);
        buffsize += WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, -1, NULL, 0, NULL, NULL);
		av_free(lpWideCharStr);
	}

    win32_argv_utf8 = (char**)av_mallocz(sizeof(char *) * (*argc_ptr + 1) + buffsize);

	for (i = 0; i < *argc_ptr; i++) 
	{
		argv = argv2[i];
		nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(char), NULL, 0);
		lpWideCharStr = (wchar_t*)av_mallocz( (nSize+1) * sizeof(wchar_t));
		memset(lpWideCharStr, 0, (nSize+1)*sizeof(wchar_t));
		nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(wchar_t), lpWideCharStr, nSize);
		nSize =WideCharToMultiByte(CP_UTF8 ,0,lpWideCharStr,-1,NULL,0,NULL,NULL);
		buf = (char*)av_mallocz( (nSize+1) * sizeof(char));//new char[nSize+1];
		memset(buf, 0, nSize+1);
		newSize = WideCharToMultiByte(CP_UTF8 ,0,lpWideCharStr,-1,buf,nSize,NULL,NULL);
		av_free(lpWideCharStr);
		win32_argv_utf8[i] = buf;
	}
	*argc_ptr = *argc_ptr;
    *argv_ptr = win32_argv_utf8;
}

int _tmain(int argc, char* argv[])
{
	///////////////////////////////////////////////////////////////////////////////  
    // ffmpeg  
    // Register all formats and codecs  
    av_register_all();  
  
    // Open video file  
    AVFormatContext *pFormatCtx = NULL;  
	prepare_app_arguments2(&argc, &argv);//轉(zhuǎn)成UTF-8
    const char* filename = "d:\\clip\\avander2.mp4";//argv[1];  
    if( avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0 ) {  
        return -1; // Couldn't open file  
    }  
  
    // Retrieve stream information  
    if( avformat_find_stream_info(pFormatCtx, NULL) < 0 ) {  
        return -1; // Couldn't find stream information  
    }  
  
    // Dump information about file onto standard error  
    av_dump_format(pFormatCtx, 0, filename, 0);  
    // Find the first video stream  
    int videoStream = -1;  
    for(int i=0; i < pFormatCtx->nb_streams; i++) {  
        if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {  
            videoStream = i;  
            break;  
        }  
    }  
    if( videoStream == -1) {  
        return -1; // Didn't find a video stream  
    }  
  
    // Get a pointer to the codec context for the video stream  
    AVCodecContext * pCodecCtx = pFormatCtx->streams[videoStream]->codec;  
  
    // Find the decoder for the video stream  
    AVCodec* pCodec = avcodec_find_decoder(pCodecCtx->codec_id);  
    if( pCodec == NULL ) {  
        fprintf(stderr, "Unsupported codec!\n");  
        return -1; // Codec not found  
    }  
  
    // Open codec  
    AVDictionary* optionsDict = NULL;  
    if( avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0 ) {  
        return -1; // Could not open codec  
    }  
	//源顏色格式
	AVPixelFormat src_fix_fmt = pCodecCtx->pix_fmt;	//AV_PIX_FMT_YUV420P
 	//目標(biāo)顏色格式
	AVPixelFormat dst_fix_fmt = PIX_FMT_BGR24;//PIX_FMT_YUV420P
   // Allocate video frame  
    AVFrame* pFrame = av_frame_alloc();  
    AVFrame* pFrameYUV = av_frame_alloc();  
    if( pFrameYUV == NULL ) {  
        return -1;  
    }  
  
    struct SwsContext* sws_ctx = sws_getContext(  
        pCodecCtx->width,  
        pCodecCtx->height,  
        pCodecCtx->pix_fmt,  
        pCodecCtx->width,  
        pCodecCtx->height,  
        dst_fix_fmt,//PIX_FMT_BGR24,//PIX_FMT_YUV420P,  
        SWS_BILINEAR,  
        NULL,  
        NULL,  
        NULL);  
  
    int numBytes = avpicture_get_size(  
        dst_fix_fmt,//PIX_FMT_YUV420P,  
        pCodecCtx->width,  
        pCodecCtx->height);  
    uint8_t* buffer = (uint8_t *)av_malloc( numBytes*sizeof(uint8_t) );  
  
    avpicture_fill((AVPicture *)pFrameYUV, buffer, dst_fix_fmt,//PIX_FMT_YUV420P,  
        pCodecCtx->width, pCodecCtx->height);  
  
    // Read frames and save first five frames to disk  
    SDL_Rect sdlRect;  
    sdlRect.x = 0;  
    sdlRect.y = 0;  
    sdlRect.w = pCodecCtx->width;  
    sdlRect.h = pCodecCtx->height;  
  
    //////////////////////////////////////////////////////  
    // SDL  
    if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER )) {  
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());  
        exit(1);  
    }  
  
    SDL_Window* sdlWindow = SDL_CreateWindow("My Game Window",  
        SDL_WINDOWPOS_UNDEFINED,  
        SDL_WINDOWPOS_UNDEFINED,  
        pCodecCtx->width,  pCodecCtx->height,  
        0);  
    if( !sdlWindow ) {  
        fprintf(stderr, "SDL: could not set video mode - exiting\n");  
        exit(1);  
    }  
  
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_TARGETTEXTURE);  //原本第三個(gè)參數(shù)是0
    SDL_Texture* sdlTexture = SDL_CreateTexture(  
        sdlRenderer,  
        SDL_PIXELFORMAT_BGR24,//SDL_PIXELFORMAT_YV12,  
        SDL_TEXTUREACCESS_STATIC,//SDL_TEXTUREACCESS_STREAMING,  
        pCodecCtx->width,  
        pCodecCtx->height);  
	if(!sdlTexture)
		return -1;
	SDL_SetTextureBlendMode(sdlTexture,SDL_BLENDMODE_BLEND );
  
    AVPacket packet;  
    SDL_Event event;  
    while( av_read_frame(pFormatCtx, &packet) >= 0 ) {  
        // Is this a packet from the video stream?  
        if( packet.stream_index == videoStream ) {  
            // Decode video frame  
            int frameFinished;  
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);  
  
            // Did we get a video frame?  
            if( frameFinished ) {  
                sws_scale(  
                    sws_ctx,  
                    (uint8_t const * const *)pFrame->data,  
                    pFrame->linesize,  
                    0,  
                    pCodecCtx->height,  
                    pFrameYUV->data,  
                    pFrameYUV->linesize  
                    );  
                  
                SDL_UpdateTexture( sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0] );  
                SDL_RenderClear( sdlRenderer );  
                SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect );  
                SDL_RenderPresent( sdlRenderer );  
            }  
            SDL_Delay(50);  
        }  
  
        // Free the packet that was allocated by av_read_frame  
        av_free_packet(&packet);  
        SDL_PollEvent(&event);  
        switch( event.type ) {  
            case SDL_QUIT:  
                SDL_Quit();  
                exit(0);  
                break;  
            default:  
                break;  
        }  
  
    }  
  
    SDL_DestroyTexture(sdlTexture);  
  
    // Free the YUV frame  
    av_free(pFrame);  
    av_free(pFrameYUV);  
  
    // Close the codec  
    avcodec_close(pCodecCtx);  
  
    // Close the video file  
    avformat_close_input(&pFormatCtx);  
  
    return 0;
}

    

上述代碼演示了怎樣把視頻幀轉(zhuǎn)換為BGR24格式,然后用SDL的紋理函數(shù)渲染到屏幕上。

不完好的地方:沒(méi)有音頻部分,更沒(méi)有視音頻同步,播放幀率固定設(shè)為20幀/秒。

演示基于SDL2.0+FFmpeg的播放器


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 成人动漫久久 | 伊人色婷婷 | 久久久夜色精品国产噜噜 | 香蕉黄色网 | 亚洲国产天堂久久九九九 | 四虎国产精品永久在线 | 91亚洲精品福利在线播放 | 国产欧美一区二区三区免费 | 国产精品三| 欧美日韩中文视频 | 97在线观看免费 | 女孕学护士一级毛片 | 成人小视频免费在线观看 | 免看一级一片一在线看 | 国产成人精品天堂 | 国产又色又爽又黄又刺激18 | 神马影院我不卡888 神马影院我不卡手机 | 欧美日韩性视频在线 | 色综合久久一本首久久 | 亚洲男人的天堂久久香蕉网 | 日韩精品欧美精品中文精品 | 手机看片一区 | 伊人久久大香线蕉综合bd高清 | 成人久久精品一区二区三区 | 奇米视频第四色 | 亚洲v在线 | 在线播放国产一区 | 午夜影院一区二区三区 | 久久线看观看精品香蕉国产 | 九九色在线视频 | 九九热在线视频播放 | 亚洲日本免费 | 亚洲精品国产专区一区 | 97视频免费人人观看人人 | 婷婷在线观看网站 | 狠狠色噜噜狠狠狠狠黑人 | 国产真实伦视频在线观看 | 老司机午夜免费 | 一区二区免费看 | 九九伦理影院手机观看 | 男人的天堂222eee |