码迷,mamicode.com
首页 > 系统相关 > 详细

用ffmpeg和SDL2实现linux player

时间:2018-02-19 11:14:49      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:des   struct   clear   access   version   mpeg   pix   etc   file   

一、version 1

#include <stdio.h>
#include <libavcodec/avcodec.h>  
#include <libavformat/avformat.h>  
#include <libswscale/swscale.h> 
#include <libavutil/imgutils.h> 
#include <SDL2/SDL.h>

int main(int argc, char *argv[])
{
    char filePath[] = "/home/lvzg/Videos/a.ts";
    int videoIndex = -1, i;
    int ret;
    int gotPicture;

    struct SwsContext *swsConvertCtx;
    AVFormatContext *pFormatCtx;
    AVCodecContext  *pCodecCtx;
    AVCodec         *pCodec;
    AVFrame         *pFrame,*pFrameYUV;
    AVPacket        *packet;
    unsigned char   *outBuffer;
    unsigned int     outBufferSize;
 
    SDL_Window      *sdlScreen;
    SDL_Renderer    *sdlRenderer;
    SDL_Texture     *sdlTexture;
    SDL_Rect         sdlRect;

    av_register_all();
 avformat_network_init();  
    pFormatCtx = avformat_alloc_context();

    if(avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0){  
        printf("Couldn't open input stream.\n");
        return -1;  
    }

    if(avformat_find_stream_info(pFormatCtx,NULL) < 0){  
        printf("Couldn't find stream information.\n");  
        return -1;  
    }

    for(i = 0; i < pFormatCtx->nb_streams; i++){
        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;  
    }

    pFrame = av_frame_alloc();
    pFrameYUV = av_frame_alloc();

    outBufferSize = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
    outBuffer = (unsigned char *)av_malloc(outBufferSize);
    avpicture_fill((AVPicture *)pFrameYUV, outBuffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
 packet = (AVPacket*)av_malloc(sizeof(AVPacket));

 swsConvertCtx = sws_getContext(
        pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
        pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
        SWS_BICUBIC, NULL, NULL, NULL);
    if(swsConvertCtx == NULL){
        goto AV_CLEAN;
    }
    
    // SDL init
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){  
        printf( "Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }

    sdlScreen = SDL_CreateWindow("Linux Media Player",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  pCodecCtx->width, pCodecCtx->height,  
        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if(!sdlScreen) {  
        printf("SDL_CreateWindow failed.\n");  
        return -1;
    }

    sdlRenderer = SDL_CreateRenderer(sdlScreen, -1, 0);
    sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YV12,
        SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);

 sdlRect.x = 0;
    sdlRect.y = 0;
    sdlRect.w = pCodecCtx->width;
    sdlRect.h = pCodecCtx->height;

    while(av_read_frame(pFormatCtx, packet) >= 0){
        if(packet->stream_index == videoIndex){
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &gotPicture, packet);
            if(ret < 0){
                printf("decode error\n");
                return -1;
            }
            if(gotPicture){
                sws_scale(swsConvertCtx, 
                    (const unsigned char * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
                    (const unsigned char * const *)pFrameYUV->data, pFrameYUV->linesize);

                SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
                    pFrameYUV->data[0], pFrameYUV->linesize[0],
                    pFrameYUV->data[1], pFrameYUV->linesize[1],
                    pFrameYUV->data[2], pFrameYUV->linesize[2]);
                SDL_RenderClear(sdlRenderer);
                SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
                SDL_RenderPresent(sdlRenderer);
                SDL_Delay(40);
            }
        }
        av_free_packet(packet);
    }
    
    sws_freeContext(swsConvertCtx);
    SDL_DestroyTexture(sdlTexture);
 SDL_Quit();
    
AV_CLEAN: 
    av_frame_free(&pFrameYUV);  
 av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
    
    return 0;
}


用ffmpeg和SDL2实现linux player

标签:des   struct   clear   access   version   mpeg   pix   etc   file   

原文地址:http://blog.51cto.com/lvzg2005/2071865

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!