zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    React视角下的轮播图
    深入理解JSX
    React.js入门笔记(再续):评论框的实现
    React.js入门笔记(续):用React的方式来思考
    React.js入门笔记
    jquery实现简单瀑布流布局(续):图片懒加载
    jquery实现简单瀑布流布局
    Node.js入门笔记(6):web开发方法
    使用X-UA-Compatible来设置IE浏览器兼容模式
    $(window).load(function() {})和$(document).ready(function(){})的区别
  • 原文地址:https://www.cnblogs.com/nanqiang/p/10951432.html
Copyright © 2011-2022 走看看