linux ffmpeg 简单视频播放器

转载 2015年11月19日 17:58:58

1.相信大家在网上看到的关于ffmpeg都已经很多了,这里我就不多介绍了,下面直接晒出代码,和自己关于ffmpeg一些体会


2.linux ffmpeg的使用步骤

初始化ffmpeg库                      av_register_all()

读取文件的头部,获取基本信息           avformat_open_input()

从头部检查文件的流信息                 avformat_find_stream_info();

获取文件的音,视频,帧率,分辨率,音频等基本信息            av_dump_format()

遍历文件中各个视频流,找到文件中第一个视频流               for(;;)

根据找到的视频流,获取对应的解码器     avcodec_find_decoder()

打开解码器                            avcodec_open2()

分配两个帧指针 pFrame pFrameRGB       pFrame解码器解码出来的帧,pFrameRGB是pFrame转化为RGB的帧

定义一个packet

while()

{

av_read_frame(); //读取一帧,存放到packet中

avcodec_decode_video2();//将packet解码成帧

定义一个AVPICTURE pict

******************

sdl一系列操作,添加一个覆盖层,获取覆盖层的数据,布长

       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];

*****************

sws_getCachedContext();//获取渲染的句柄

sws_scale(pict,...pFrame); //将pFrame 渲染到pict对应的图层中

av_free_packet();//释放帧

}


3.晒出代码

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>

int main(int argc, char *argv[]) 
{
AVFormatContext *pFormatCtx; //输入输出的容器,但不能同时作为输入和输出的容器
int i, videoStream;
AVCodecContext *pCodecCtx;   //动态的记录一个解码器的上下文
AVCodec *pCodec;    //解码器是由链表组成的,链表的类型是AVCodec
AVFrame *pFrame;    //用来保存数据缓存的对象
AVFrame *pFrameRGB;
AVPacket packet;    //主要记录音视频数据帧,时钟信息和压缩数据首地址,大小等信息
int frameFinished = 0;
int numBytes;
uint8_t *buffer;
struct SwsContext *pSwsCtx;  //视频分辨率,色彩空间变换时所需要的上下文句柄

av_register_all();
const char *filename = "/home/crazy/桌面/sdl/encoder.264";

//读取文件的头部并且把信息保存到pFormatCtx    检测了文件的头部
pFormatCtx=avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filename, NULL,NULL) != 0)
return -1; 

//从文件的头部,检查文件中的流的信息
if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
return -1; // Couldn't find stream information




//负责为pFormatCtx->streams填上正确的信息,pFormatCtx->streams仅仅是一组大小为pFormatCtx->nb_streams的指针
av_dump_format(pFormatCtx, 0, filename, 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


// 得到解码器的上下文信息
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,NULL) < 0)
return -1; // Could not open codec


// Allocate video frame
pFrame = avcodec_alloc_frame();


// Allocate an AVFrame structure
pFrameRGB = avcodec_alloc_frame();
if (pFrameRGB == NULL)
return -1;


// 计算AVCodeContext缓冲区的大小和申请空间
numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
//申请内存对齐
buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));



//给pFrameRGB 分配内存
avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);




while (av_read_frame(pFormatCtx, &packet) >= 0)

       {
if (packet.stream_index == videoStream)

               {
pFrame = avcodec_alloc_frame();
int w = pCodecCtx->width;
int h = pCodecCtx->height;
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);//把包转化为帧
pSwsCtx = sws_getContext(w, h, pCodecCtx->pix_fmt, w, h,PIX_FMT_RGB565, SWS_POINT, NULL, NULL, NULL); //负责得到视频分辨率,色彩控件变换时的上下文句柄
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) 

                       {
fprintf(stderr, "Could not initialize SDL - %s/n",
SDL_GetError());
exit(1);
}
SDL_Surface *screen;
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0,0);
if (!screen) 

                       {
fprintf(stderr, "SDL: could not set video mode - exiting/n");
exit(1);
}
SDL_Overlay *bmp;
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen);
SDL_Rect rect;
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];//pitches是指YUV存储数据对应的stride(步长)
pict.linesize[1] = bmp->pitches[2];
pict.linesize[2] = bmp->pitches[1];
// Convert the image into YUV format that SDL uses
img_convert(&pict, PIX_FMT_YUV420P, (AVPicture *) pFrame,pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height);
SDL_UnlockYUVOverlay(bmp);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp, &rect);
}
SDL_Event event;
av_free_packet(&packet);
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
SDL_Quit();
exit(0);
break;
default:
break;
}
}
}

av_free(buffer);
av_free(pFrameRGB);


av_free(pFrame);


avcodec_close(pCodecCtx);


avformat_close_input(&pFormatCtx);


return 0;
}
int   img_convert(AVPicture *dst, enum PixelFormat dst_pix_fmt,const AVPicture *src, enum PixelFormat src_pix_fmt, int src_width,int src_height)

 {
int w;
int h;
struct SwsContext *pSwsCtx;


w = src_width;
h = src_height;
pSwsCtx = sws_getContext(w, h, src_pix_fmt, w, h, dst_pix_fmt, SWS_BICUBIC,
NULL, NULL, NULL);


sws_scale(pSwsCtx, (const uint8_t * const *)src->data, src->linesize, 0, h, dst->data,
dst->linesize);//把RGB转化为image
//这样释放掉pSwsCtx的内存

return 0;
}


4.makefile编译

a.out:testvideo.c

gcc testvideo.c  -lavformat -lavcodec -lavutil -lswscale -lm -lz  -lSDL -lpthread


5.关于代码补充

        代码实现的功能还是很简单的,只实现了基本的视频播放,没有实现音频,字幕等,只希望抛砖引玉,如果还有谁能完善代码,希望和我交流;


同时要提醒大家的是,不同的每个人下载的ffmpeg的库也许是不相同的,所以在编译是会出现很多函数找不到的情况,如果发生了该问题,解决方法如下

比如avformat_open_input()函数找不到

           grep -R avformat_open_input /usr/include  

          在接下来会看到有关api chang 一些的文章,根据api change 提到的改成自己库中支持的函数,我就是自己根据这种方法,改了很多函数,如果有什么特殊情况,可在下面留言!

6.补充

大家转载是希望表明出处,谢谢!

最简单的基于FFMPEG+SDL的视频播放器(Linux)

  • 2014年07月30日 21:58
  • 4KB
  • 下载

ffmpeg教程

转自:http://blog.csdn.net/kl222/article/details/7819301   ffmpeg教程五 —— 使用举例 1.1.1    截取一张352x240尺寸大小的,...
  • zhichao2001
  • zhichao2001
  • 2013年10月11日 08:48
  • 11278

FFMEG开发教程--(01)ffmpeg基本使用流程

概要 电影文件有很多基本的组成部分。首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。AVI和Quicktime就 是容器的例子。接着,你有一组流,例如,...
  • superfang119
  • superfang119
  • 2013年01月21日 15:05
  • 3879

Android平台上使用SDL官方demo播放视频(使用ffmpeg最新版解码)

SDL(Simple Directmedia Layer)是一套开源的跨平台多媒体开发库,集成了音视频的许多底层的API,介绍Windows平台下的例子已经很多了,例如:雷老师的 最简单的视音频播放示...
  • danjuan123
  • danjuan123
  • 2017年03月23日 15:19
  • 2164

从零开始学习音视频编程技术(六) FFMPEG Qt视频播放器之显示图像

原文地址:http://blog.yundiantech.com/?log=blog&id=9 前面讲解了如何用FFMPEG解码视频。 现在,我们就着手用FFMPEG+Qt写一个视...
  • qq214517703
  • qq214517703
  • 2016年09月22日 10:01
  • 3482

从零开始学习音视频编程技术(七) FFMPEG Qt视频播放器之SDL的使用

原文地址:http://blog.yundiantech.com/?log=blog&id=10 前面介绍了使用FFMPEG+Qt解码视频并显示。 现在我们就着手给它加上声音播放。 ...
  • qq214517703
  • qq214517703
  • 2016年09月22日 10:13
  • 2222

linux ffmpeg 简单视频播放器

  • 2013年02月21日 19:29
  • 6KB
  • 下载

最简单的基于FFMPEG+SDL的视频播放器(Linux)

  • 2014年07月30日 21:58
  • 4KB
  • 下载

ffmpeg简单视频播放器

参考学习雷霄骅的最简单的基于FFMPEG视频播放器。 在移植代码到我的linux环境中时总出现问题,所以干脆把雷神的代码从头到尾分析并移植过来调试。 开发环境:   操作系统:ubuntu14 ...
  • dapangzi88
  • dapangzi88
  • 2017年01月26日 17:28
  • 72

最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

之前做过一个FFMPEG+SDL的简单播放器:《100行代码实现最简单的基于FFMPEG+SDL的视频播放器》。最近有不少人反映SDL已经升级到2.0版本了,甚至官网的Wiki上都只有SDL2.0的文...
  • leixiaohua1020
  • leixiaohua1020
  • 2014年08月31日 01:20
  • 71093
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux ffmpeg 简单视频播放器
举报原因:
原因补充:

(最多只允许输入30个字)