FFmpeg C++ Video || Audio 解碼

---------- FFmepg官網 ----------
---------- FFmepg簡介 ----------
本文主要用于FFmpeg for C++入門介紹和學習巷波,若您發(fā)現文章中錯誤或者對文章內容有疑問,請在留言區(qū)留言粱栖。謝謝蔑歌!

下載編譯FFmpeg-lib

環(huán)境:CentOS 7 FFmpeg 版本:3.3

#!/bin/bash
set -o errexit

# Download ffmpeg-3.3
mkdir ffmpeg -p
wget http://ffmpeg.org/releases/ffmpeg-3.3.tar.bz2 -O ffmpeg/ffmpeg-3.3.tar.bz2

# Untar ffmpeg-3.3
cd ffmpeg
tar xvf ffmpeg-3.3.tar.bz2
cd ffmpeg-3.3

# Build ffmpeg
./configure --enable-pic --enable-shared
make

# Prepare the output package
mkdir ffmpeg-lib -p
mkdir ffmpeg-lib/lib -p
mkdir ffmpeg-lib/inc -p
libarr=("avcodec" "avdevice" "avfilter" "avformat" "avutil" "swresample" "swscale")
for lib in ${libarr[@]}; do
    echo "Copy lib and header for $lib"
    cp lib${lib}/lib${lib}.so* ffmpeg-lib/lib/ -av
    mkdir -p ffmpeg-lib/inc/lib${lib}
    cp lib${lib}/*.h ffmpeg-lib/inc/lib${lib}/
done
# Create ffmpeg artifact
tar -cpzvf ffmpeg-lib.tar.gz ffmpeg-lib

將代碼copy到bash腳本,執(zhí)行就可以得到ffmpeg-lib责蝠。

Audio || Video decode

解壓編譯得到的ffmpeg-lib.tar.gz
新建文件 decode.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>

extern "C" {
#include <libavcodec/avcodec.h>
}

#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,
                   FILE *outfile)
{
    int i, ch;
    int ret, data_size;

    /* send the packet with the compressed data to the decoder */
    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Error submitting the packet to the decoder\n");
        exit(1);
    }

    /* read all the output frames (in general there may be any number of them */
    while (ret >= 0) {
        ret = avcodec_receive_frame(dec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during decoding\n");
            exit(1);
        }
        data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);
        if (data_size < 0) {
            /* This should not occur, checking just for paranoia */
            fprintf(stderr, "Failed to calculate data size\n");
            exit(1);
        }
        for (i = 0; i < frame->nb_samples; i++)
            for (ch = 0; ch < dec_ctx->channels; ch++)
                fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile);
    }
}

int main(int argc, char* argv[])
{
    const char *outfilename, *filename;
    const AVCodec *codec;
    AVCodecContext *c= NULL;
    AVCodecParserContext *parser = NULL;
    int len, ret;
    FILE *f, *outfile;
    uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t *data;
    size_t   data_size;
    AVPacket *pkt;
    AVFrame *decoded_frame = NULL;

    if (argc <= 2) {
        fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
        exit(0);
    }
    filename    = argv[1];
    outfilename = argv[2];
    
    avcodec_register_all();
    pkt = av_packet_alloc();

    /* find the MPEG audio decoder */
    codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }

    parser = av_parser_init(codec->id);
    if (!parser) {
        fprintf(stderr, "Parser not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }
    outfile = fopen(outfilename, "wb");
    if (!outfile) {
        av_free(c);
        exit(1);
    }

    /* decode until eof */
    data      = inbuf;
    data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

    while (data_size > 0) {
        if (!decoded_frame) {
            if (!(decoded_frame = av_frame_alloc())) {
                fprintf(stderr, "Could not allocate audio frame\n");
                exit(1);
            }
        }

        ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,
                               data, data_size,
                               AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        if (ret < 0) {
            fprintf(stderr, "Error while parsing\n");
            exit(1);
        }
        data      += ret;
        data_size -= ret;

        if (pkt->size)
            decode(c, pkt, decoded_frame, outfile);

        if (data_size < AUDIO_REFILL_THRESH) {
            memmove(inbuf, data, data_size);
            data = inbuf;
            len = fread(data + data_size, 1,
                        AUDIO_INBUF_SIZE - data_size, f);
            if (len > 0)
                data_size += len;
        }
    }

    /* flush the decoder */
    pkt->data = NULL;
    pkt->size = 0;
    decode(c, pkt, decoded_frame, outfile);

    fclose(outfile);
    fclose(f);

    avcodec_free_context(&c);
    av_parser_close(parser);
    av_frame_free(&decoded_frame);
    av_packet_free(&pkt);

    return 0;
}

注意:
avcodec_register_all(); 注冊編解碼器
codec = avcodec_find_decoder(AV_CODEC_ID_AAC); 查找音視頻解碼器,可替換成AV_CODEC_ID_MP3,AV_CODEC_ID_H264等等
編譯并執(zhí)行.out

[root@Jelly-Test-119 ~]# g++ -std=c++11 -I ffmpeg-lib/inc decode.cpp -L ffmpeg-lib/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -o decode.out
[root@Jelly-Test-119 ~]# export LD_LIBRARY_PATH=ffmpeg-lib/lib
[root@Jelly-Test-119 ~]# ./decode.out test.mp3 jelly.mp3

到這里我們就完成了一個簡單的ffmpeg decode demo了墨辛。


歡迎提出和糾正問題躲因!
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末棘伴,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子摩骨,更是在濱河造成了極大的恐慌通贞,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恼五,死亡現場離奇詭異昌罩,居然都是意外死亡,警方通過查閱死者的電腦和手機灾馒,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門茎用,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人睬罗,你說我怎么就攤上這事轨功。” “怎么了傅物?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵夯辖,是天一觀的道長琉预。 經常有香客問我董饰,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任卒暂,我火速辦了婚禮啄栓,結果婚禮上,老公的妹妹穿的比我還像新娘也祠。我一直安慰自己昙楚,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布诈嘿。 她就那樣靜靜地躺著堪旧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奖亚。 梳的紋絲不亂的頭發(fā)上淳梦,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音昔字,去河邊找鬼爆袍。 笑死,一個胖子當著我的面吹牛作郭,可吹牛的內容都是我干的陨囊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼夹攒,長吁一口氣:“原來是場噩夢啊……” “哼蜘醋!你這毒婦竟也來了?” 一聲冷哼從身側響起芹助,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤堂湖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后状土,有當地人在樹林里發(fā)現了一具尸體无蜂,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年蒙谓,在試婚紗的時候發(fā)現自己被綠了斥季。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡累驮,死狀恐怖酣倾,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情谤专,我是刑警寧澤躁锡,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站置侍,受9級特大地震影響映之,放射性物質發(fā)生泄漏拦焚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一杠输、第九天 我趴在偏房一處隱蔽的房頂上張望赎败。 院中可真熱鬧,春花似錦蠢甲、人聲如沸僵刮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搞糕。三九已至,卻和暖如春曼追,著一層夾襖步出監(jiān)牢的瞬間寞宫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工拉鹃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辈赋,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓膏燕,卻偏偏與公主長得像钥屈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坝辫,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容