如下利用SDL播放網絡流,須要本身配置運行環境,包括SDL和FFmpegios
// 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("沒法打開文件\n"); return -1; } if (avformat_find_stream_info(pFormatCtx, NULL)<0)//查找流信息 { printf("Couldn't find stream information.\n"); 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.\n"); return -1; } pCodecCtx = pFormatCtx->streams[videoindex]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找解碼器 if (pCodec == NULL) { printf("Codec not found.\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)//打開解碼器 { printf("Could not open codec.\n"); 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\n", 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\n"); 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("文件信息-----------------------------------------\n"); //av_dump_format(pFormatCtx,0,filepath,0); printf("-------------------------------------------------\n"); //------------------------------ 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("解碼錯誤\n"); 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\n"); ffplayer(); system("pause"); return 0; }