linux ffmpeg 簡單視頻播放器

來源:互聯網
上載者:User

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 提到的改成自己庫中支援的函數,我就是自己根據這種方法,改了很多函數,如果有什麼特殊情況,可在下面留言!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.