//
// main.cpp
// ffmpeg03
//
// Created by 史明 on 16/11/3.
// [email protected]
// gcc main.c -lavformat -lavcodec `pkg-config --cflags --libs sdl2` -o main.out
// compile on mac OS X EI capitan 10.11.6 as following.
// gcc main.cpp `pkg-config --cflags --libs libavcodec libavformat sdl2` -o out.out
// Copyright © 2016年 史明. All rights reserved.
//
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "SDL2/SDL.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
};
#endif
#endif
const char path[] = "/Users/shiming/ffmpegResearch/FFmpeg-Tutorial/ss1-part.mp4";
//const char path[] = "/Users/shiming/Downloads/independent.rmvb";
int main(int argc, const char * argv[]) {
// insert code here...
int errCode = -1;
int videoStreamID = -1;
AVFormatContext *pAVFmtCtx;
AVCodecContext *pAVCodecCtx;
AVCodec *pAVCodec;
AVCodecParameters *pAVCodecPars;
AVFrame *pAVFrame;
AVPacket *pAVPacket;
//SDL 相關
int screen_w,screen_h;
SDL_Window *screen;
SDL_Renderer* sdlRenderer;
SDL_Texture* sdlTexture;
//std::cout << "Hello, World!\n";
//註冊編解碼器和一些其他的東西
av_register_all();
//打開流媒體
if((errCode = avformat_open_input(&pAVFmtCtx, path, NULL, NULL) < 0)) {
printf("open input file fail! err code :%d", errCode);
return errCode;
}
//獲取流媒體信息
if((errCode = avformat_find_stream_info(pAVFmtCtx, NULL)) < 0) {
printf("find input file info fail! err code :%d", errCode);
return errCode;
}
//dump the info of media file onto standard err
av_dump_format(pAVFmtCtx, 0, path, 0);
for (int i = 0; i < pAVFmtCtx->nb_streams; ++i) {
if (AVMEDIA_TYPE_VIDEO == pAVFmtCtx->streams[i]->codecpar->codec_type) {
printf("video stream id : %d\n", i);
videoStreamID = i;
}
}
if (videoStreamID == -1) {
printf("find stream id failed!");
return -1;
}
pAVCodecPars = pAVFmtCtx->streams[videoStreamID]->codecpar;
//尋找解碼器,並申請解碼器的上下文
pAVCodec = avcodec_find_decoder(pAVCodecPars->codec_id);
pAVCodecCtx = avcodec_alloc_context3(pAVCodec);
if((errCode = avcodec_parameters_to_context(pAVCodecCtx, pAVCodecPars)) < 0) {
printf("copy the codec parameters to context fail, err code : %d\n", errCode);
return errCode;
}
//打開解碼器,如果要使用av_send_frame和av_receive_frame就必須才用這種方式打開
if((errCode = avcodec_open2(pAVCodecCtx, pAVCodec, NULL)) < 0){
printf("open codec failed ! errcode : %d", errCode);
return errCode;
}
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf("init sdl failed! -%s\n", SDL_GetError());
return -1;
}
screen_h = pAVCodecPars->height;
screen_w = pAVCodecPars->width;
screen = SDL_CreateWindow("Player demo window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL);
if (!screen) {
printf("create window failed %s", SDL_GetError());
}
sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pAVCodecPars->width,pAVCodecPars->height);
pAVFrame = av_frame_alloc();
pAVPacket = av_packet_alloc();
int retCode = -1;
while (av_read_frame(pAVFmtCtx, pAVPacket) >= 0) {
if (pAVPacket->stream_index == videoStreamID) {
retCode = avcodec_send_packet(pAVCodecCtx, pAVPacket);
if(!retCode) {
retCode = avcodec_receive_frame(pAVCodecCtx, pAVFrame);
switch (retCode) {
case 0:
printf("decode a frame success\n");
SDL_UpdateYUVTexture( sdlTexture, NULL, pAVFrame->data[0], pAVFrame->linesize[0],
pAVFrame->data[1], pAVFrame->linesize[1],
pAVFrame->data[2], pAVFrame->linesize[2]);
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent( sdlRenderer );
SDL_Delay(40);
break;
case AVERROR_EOF:
printf("the decoder has been fully flushed,\
and there will be no more output frames.\n");
break;
case AVERROR(EAGAIN):
printf("Resource temporarily unavailable\n");
break;
case AVERROR(EINVAL):
printf("Invalid argument\n");
break;
default:
break;
}
}
}
av_packet_unref(pAVPacket);
}
SDL_Quit();
av_free(pAVFrame);
av_free(pAVPacket);
avcodec_close(pAVCodecCtx);
avformat_close_input(&pAVFmtCtx);
return 0;
}
編譯此程序前,請確保安裝了SDL2,下載地址:http://www.libsdl.org/download-2.0.php
勞動可貴,歡迎轉載,請註明出處~
http://blog.csdn.net/minger1202/article/details/52469056