//
// main.cpp
// ffmpeg03
//
// Created by 史明 on 16/11/3.
// sminger1202@gmail.com
// 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.youkuaiyun.com/minger1202/article/details/52469056