您的位置:首页 > 其它

ffmpeg (二):ffmpeg结合SDL2.0解码视频流

2016-10-09 22:21 453 查看
转自:http://blog.csdn.net/oldmtn/article/details/20284721

看了http://blog.csdn.NET/leixiaohua1020/article/details/8652605后,想学习在windows下面使用ffmpeg库播放视频。

100行代码实现最简单的基于FFMPEG+SDL的视频播放器》:

该文章里面是使用ffmpeg结合SDL1.2解码视频的。其中用到了SDL_CreateYUVOverlay,SDL_Overlay等函数在SDL2.0已经不存在了。

因此需要想新的办法。

这里需要给自己先补点知识:

SDL(Simple DirectMedia Layer): 是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac
OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

经过多方的查询,参考了N多资料。解决了。

参考资料:

1. http://blog.csdn.net/ashqal/article/details/17640179
2. http://stackoverflow.com/questions/17579286/sdl2-0-alternative-for-sdl-overlay
3. http://wiki.libsdl.org/MigrationGuide
4. http://blog.csdn.net/leixiaohua1020/article/details/12747899
5. http://blog.csdn.net/leixiaohua1020/article/details/8652605
6. https://github.com/chelyaev/ffmpeg-tutorial
下面的代码,是我自己根据上面帖子里面代码修改的。

[cpp] view
plain copy

 print?





#include <stdio.h>  

#include <tchar.h>  

#include <io.h>  

#include <direct.h>  

extern "C"  

{  

    // ffmpeg  

#include "libavcodec/avcodec.h"  

#include "libavformat/avformat.h"  

#include "libswscale/swscale.h"  

    // SDL  

#include "sdl/SDL.h"  

#include "sdl/SDL_thread.h"  

};  

  

#pragma comment(lib,"avutil.lib")  

#pragma comment(lib,"avcodec.lib")  

#pragma comment(lib,"avformat.lib")  

#pragma comment(lib,"swscale.lib")  

#pragma comment(lib,"sdl2.lib")  

  

int _tmain(int argc, char *argv[])  

{  

    ///////////////////////////////////////////////////////////////////////////////  

    // ffmpeg  

    // Register all formats and codecs  

    av_register_all();  

  

    // Open video file  

    AVFormatContext *pFormatCtx = NULL;  

    const char* filename = "cuc_ieschool.flv";  

    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  

    }  

  

    // 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,  

        PIX_FMT_YUV420P,  

        SWS_BILINEAR,  

        NULL,  

        NULL,  

        NULL);  

  

    int numBytes = avpicture_get_size(  

        PIX_FMT_YUV420P,  

        pCodecCtx->width,  

        pCodecCtx->height);  

    uint8_t* buffer = (uint8_t *)av_malloc( numBytes*sizeof(uint8_t) );  

  

    avpicture_fill((AVPicture *)pFrameYUV, buffer, 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, 0);  

    SDL_Texture* sdlTexture = SDL_CreateTexture(  

        sdlRenderer,  

        SDL_PIXELFORMAT_YV12,  

        SDL_TEXTUREACCESS_STREAMING,  

        pCodecCtx->width,  

        pCodecCtx->height);  

  

    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;  

}  

大家可以在这里下载《ffmpeg结合SDL2.0最简单的工程》,根据上面几个帖子,相信大家可以成功的。
PS: 由于写这篇文章的时候,CSDN上传资源有问题,待可以上传的时候,我再上传。

步骤:

1.下载SDL2.0 地址:http://www.libsdl.org/

2.下载ffmpeg在Windows下的SDK 地址:http://ffmpeg.zeranoe.com/builds/

3.下载MinGW // 可以在CSDN下载绿色版 地址:http://download.csdn.net/detail/piano7heart/3651248

下面打算学习如何使用ffmpeg解码音频流。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: