SDL 小例子

以下利用SDL播放网络流,需要自己配置运行环境,包括SDL和FFmpeg

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
/*
#include "stdafx.h"


#include <iostream>

#define SDL_MAIN_HANDLED

#include "SDL.h"


int main()
{
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
    {
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }
    SDL_Quit();
    system("pause");
    return 0;
}
*/
#include "stdafx.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include "SDL.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#ifdef __cplusplus
}
#endif

int ffplayer()
{
    AVFormatContext    *pFormatCtx;
    int                i, videoindex;
    AVCodecContext    *pCodecCtx;
    AVCodec            *pCodec;
    //char filepath[]="F:\Work\ffmpegdemo\Debug\Wildlife.wmv";
    char rtspUrl[] = "rtmp://58.200.131.2:1935/livetv/cctv1";

    //char rtspUrl[] = "rtmp://192.168.1.253/live/41";
    av_register_all();//注册组件
    avformat_network_init();//支持网络流
    pFormatCtx = avformat_alloc_context();//初始化AVFormatContext
    if (avformat_open_input(&pFormatCtx,/*filepath*/rtspUrl, NULL, NULL) != 0) {//打开文件或网络流
        printf("无法打开文件
");
        return -1;
    }
    if (avformat_find_stream_info(pFormatCtx, NULL)<0)//查找流信息
    {
        printf("Couldn't find stream information.
");
        return -1;
    }
    videoindex = -1;
    for (i = 0; i<pFormatCtx->nb_streams; i++) //获取视频流ID
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoindex = i;
            break;
        }
    if (videoindex == -1)
    {
        printf("Didn't find a video stream.
");
        return -1;
    }
    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器
    if (pCodec == NULL)
    {
        printf("Codec not found.
");
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)//打开解码器
    {
        printf("Could not open codec.
");
        return -1;
    }
    AVFrame    *pFrame, *pFrameYUV;
    pFrame = av_frame_alloc();//存储解码后AVFrame
    pFrameYUV = av_frame_alloc();//存储转换后AVFrame
    uint8_t *out_buffer;
    out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];//分配AVFrame所需内存
    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//填充AVFrame

    //------------SDL初始化--------
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        printf("Could not initialize SDL - %s
", SDL_GetError());
        return -1;
    }
    SDL_Window *screen = SDL_CreateWindow("RTSP Client Demo",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        1280, 720,
        SDL_WINDOW_RESIZABLE/* SDL_WINDOW_HIDDEN*/ | SDL_WINDOW_OPENGL);
    if (!screen) {
        printf("SDL: could not set video mode - exiting
");
        return -1;
    }
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    SDL_Texture* sdlTexture = SDL_CreateTexture(
        sdlRenderer,
        SDL_PIXELFORMAT_YV12,
        SDL_TEXTUREACCESS_STREAMING,
        pCodecCtx->width,
        pCodecCtx->height);

    SDL_Rect rect;
    SDL_Rect dstRect;
    dstRect.x = 0;
    dstRect.y = 0;
    dstRect.w = 1280;
    dstRect.h = 720;
    //-----------------------------
    int ret, got_picture;
    static struct SwsContext *img_convert_ctx = NULL;
    int y_size = pCodecCtx->width * pCodecCtx->height;

    SDL_Event event;
    AVPacket *packet = (AVPacket *)malloc(sizeof(AVPacket));//存储解码前数据包AVPacket
    av_new_packet(packet, y_size);
    //输出一下信息-----------------------------
    printf("文件信息-----------------------------------------
");
    //av_dump_format(pFormatCtx,0,filepath,0);
    printf("-------------------------------------------------
");
    //------------------------------
    while (1)//循环获取压缩数据包AVPacket
    {
        if (av_read_frame(pFormatCtx, packet) >= 0)
        {
            if (packet->stream_index == videoindex)
            {
                ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);//解码。输入为AVPacket,输出为AVFrame
                if (ret < 0)
                {
                    printf("解码错误
");
                    return -1;
                }
                if (got_picture)
                {
                    //像素格式转换。pFrame转换为pFrameYUV。
                    //if(img_convert_ctx == NULL)
                        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
                    sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
                    sws_freeContext(img_convert_ctx);
                    //------------SDL显示--------
                    rect.x = 0;
                    rect.y = 0;
                    rect.w = pCodecCtx->width;
                    rect.h = pCodecCtx->height;

                    SDL_UpdateTexture(sdlTexture, &rect, pFrameYUV->data[0], pFrameYUV->linesize[0]);
                    SDL_RenderClear(sdlRenderer);
                    SDL_RenderCopy(sdlRenderer, sdlTexture, &rect, &dstRect);
                    SDL_RenderPresent(sdlRenderer);
                    //延时20ms
                    SDL_Delay(20);
                    //------------SDL-----------
                }
            }        
        }        
        av_free_packet(packet);
        SDL_PollEvent(&event);
        switch (event.type) {
        case SDL_QUIT:
            SDL_Quit();
            exit(0);
            break;
        default:
            break;
        }
    }
    //sws_freeContext(img_convert_ctx);
    SDL_DestroyTexture(sdlTexture);
    delete[] out_buffer;
    av_free(pFrameYUV);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    printf("hello
");

    ffplayer();

    system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/nanqiang/p/10951432.html