Tutorial 02: Outputting to the Screen

来源:互联网 发布:视频播放cms 编辑:程序博客网 时间:2024/05/25 19:55

这个例子主要是播放视频的,和tutorial01有很多相似的地方。

这里就不一一叙述了。


// tutorial02.c// A pedagogical video player that will stream through every video frame as fast as it can.//// This tutorial was written by Stephen Dranger (dranger@gmail.com).//// Code based on FFplay, Copyright (c) 2003 Fabrice Bellard, // and a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)// Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1//// Use the Makefile to build all examples.//// Run using// tutorial02 myvideofile.mpg//// to play the video stream on your screen.extern "C"{#include "libavutil/avstring.h"#include "libavutil/mathematics.h"#include "libavutil/pixdesc.h"#include "libavutil/imgutils.h"#include "libavutil/dict.h"#include "libavutil/parseutils.h"#include "libavutil/samplefmt.h"#include "libavutil/avassert.h"#include "libavutil/time.h"#include "libavformat/avformat.h"#include "libavdevice/avdevice.h"#include "libswscale/swscale.h"#include "libavutil/opt.h"#include "libavcodec/avfft.h"#include "libswresample/swresample.h"#include "SDL1.2/SDL.h"#include "SDL1.2/SDL_thread.h"}#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "avutil.lib")#pragma comment(lib, "avdevice.lib")#pragma comment(lib, "avfilter.lib")#pragma comment(lib, "postproc.lib")#pragma comment(lib, "swresample.lib")#pragma comment(lib, "swscale.lib")#pragma comment(lib, "SDL.lib")#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#include <stdio.h>int _tmain() {    AVFormatContext *pFormatCtx = NULL;    int             i, videoStream;    AVCodecContext  *pCodecCtx = NULL;    AVCodec         *pCodec = NULL;    AVFrame         *pFrame = NULL;     AVPacket        packet;    int             frameFinished;    //float           aspect_ratio;    AVDictionary    *optionsDict = NULL;    struct SwsContext *sws_ctx = NULL;    SDL_Overlay     *bmp = NULL;    SDL_Surface     *screen = NULL;    SDL_Rect        rect;    SDL_Event       event;    char szFile[] = "song.flv";    av_register_all();    if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) ) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if( avformat_open_input(&pFormatCtx, szFile, 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, szFile, 0);    // Find the first video stream    videoStream = -1;    for( 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    pCodecCtx = pFormatCtx->streams[videoStream]->codec;    // Find the decoder for the video stream    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);    if( pCodec == NULL ) {        fprintf(stderr, "Unsupported codec!\n");        return -1; // Codec not found    }    // Open codec    if( avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0 ) {        return -1; // Could not open codec    }    // Allocate video frame    pFrame = av_frame_alloc();    // Make a screen to put our video#ifndef __DARWIN__    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);#else    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);#endif    if( !screen ) {        fprintf(stderr, "SDL: could not set video mode - exiting\n");        exit(1);    }    // Allocate a place to put our YUV image on that screen    bmp = SDL_CreateYUVOverlay(pCodecCtx->width,        pCodecCtx->height,        SDL_YV12_OVERLAY,        screen);
    // 将解码得到的视频格式转化为YUV420格式.    sws_ctx =        sws_getContext        (        pCodecCtx->width,        pCodecCtx->height,        pCodecCtx->pix_fmt,        pCodecCtx->width,        pCodecCtx->height,        PIX_FMT_YUV420P,        SWS_BILINEAR,        NULL,        NULL,        NULL        );    // Read frames and save first five frames to disk    i = 0;    while( av_read_frame(pFormatCtx, &packet) >= 0 ) {        // Is this a packet from the video stream?        if( packet.stream_index == videoStream ) {            // Decode video frame            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,                 &packet);            // Did we get a video frame?            if( frameFinished ) {                SDL_LockYUVOverlay(bmp);                AVPicture pict;                pict.data[0] = bmp->pixels[0];                pict.data[1] = bmp->pixels[2];                pict.data[2] = bmp->pixels[1];                pict.linesize[0] = bmp->pitches[0];                pict.linesize[1] = bmp->pitches[2];                pict.linesize[2] = bmp->pitches[1];                // Convert the image into YUV format that SDL uses                sws_scale                    (                    sws_ctx,                     (uint8_t const * const *)pFrame->data,                     pFrame->linesize,                     0,                    pCodecCtx->height,                    pict.data,                    pict.linesize                    );                SDL_UnlockYUVOverlay(bmp);                rect.x = 0;                rect.y = 0;                rect.w = pCodecCtx->width;                rect.h = pCodecCtx->height;                SDL_DisplayYUVOverlay(bmp, &rect);                SDL_Delay(40);            }        }        // 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;        }    }    // Free the YUV frame    av_free(pFrame);    // Close the codec    avcodec_close(pCodecCtx);    // Close the video file    avformat_close_input(&pFormatCtx);    return 0;}

只是把有区别的地方说一下。


因为SDL能播放的是YUV420格式,所以需要将解码后得到的视频转码为YUV420格式。



另外每解码,播放一帧,需要暂停40ms,因为若不暂停,那么播放速度是等于解码速度的,视频会迅速播放完。



0 0
原创粉丝点击