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

演示基于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精品国产乱码在线观看 | 国产极品嫩模在线观看91精品 | 日本成人久久 | 99热免费 | 婷婷在线成人免费观看搜索 | 精品精品国产自在久久高清 | 一级毛片看看 | 99视频在线观看免费 | 天天干天天干天天插 | 无毒不卡在线播放 | 亚洲高清视频在线 | 天天干天天做 | 国产精品久久久久久久久kt | 国产农村1级毛片 | 中文字幕日韩精品亚洲七区 | 中文字幕亚洲综合久久 | 色中色官网 | 日日日日干| 91麻豆精品国产91久久久久久 | 日本免费一二三区 | 中文字字幕在线 | 日本不卡免费高清一级视频 | 日本草草影院 | 日韩美在线 | 天天弄天天干 | 国产一国产一级毛片视频在线 | 乱色欧美videos黑人 | 国产成人精品一区二区三在线观看 | 欧美成人免费mv在线播放 | 亚洲伊人tv综合网色 | 亚洲综合成人在线 | 在线人成精品免费视频 | 国产成人一区二区视频在线观看 | 特级黄色毛片 | 精品一区二区久久 | 中文字幕亚洲综合精品一区 |