转:Android上ffmpeg移植(1)

本文详细记录了将FFmpeg从Linux移植到Android的过程,并重点介绍了如何处理音频操作上的差异。通过代码示例展示了关键步骤,包括文件头的编写和音频数据的读取、解码与写入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在移植ffmpeg到android,今天花了大半天的时间终于把ffmpeg移植到linux下面,下一步就是移植到android框架中,这里关于ffmpeg的音频操作,和视频有很大的区别,话不多说,直接上代码。代码有点乱,调试了很长时间。

#include <stdlib.h>
#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;

typedef struct
{
    char chChunkID[4];
    int nChunkSize;
}XCHUNKHEADER;

typedef struct
{
    short nFormatTag;

    short nChannels;

    int nSamplesPerSec;

    int nAvgBytesPerSec;

    short nBlockAlign;

    short nBitsPerSample;

}WAVEFORMAT;

typedef struct
{
    short nFormatTag;

    short nChannels;

    int nSamplesPerSec;

    int nAvgBytesPerSec;

    short nBlockAlign;

    short nBitsPerSample;

    short nExSize;

}WAVEFORMATX;

typedef struct
{
    char chRiffID[4];

    int nRiffSize;

    char chRiffFormat[4];

}RIFFHEADER;

typedef struct
{
    char chFmtID[4];

    int nFmtSize;

    WAVEFORMAT wf;

}FMTBLOCK;

void WriteWAVEFileHeader(FILE* fpwave, int len)
{
    RIFFHEADER riff;

    FMTBLOCK fmt;

    XCHUNKHEADER chunk;

    WAVEFORMATX wfx;

    char tag[10] = "";

    // 1. ÐŽRIFFÍ·

    strcpy(tag, "RIFF");

    memcpy(riff.chRiffID, tag, 4);

    riff.nRiffSize = 4                                     // WAVE

        + sizeof(XCHUNKHEADER)               // fmt

        + sizeof(WAVEFORMATX)           // WAVEFORMATX

        + sizeof(XCHUNKHEADER)               // DATA

        + len*sizeof(char);    //

    strcpy(tag, "WAVE");

    memcpy(riff.chRiffFormat, tag, 4);

    fwrite(&riff, 1, sizeof(RIFFHEADER), fpwave);

    // 2. ÐŽFMT¿é

    strcpy(tag, "fmt ");

    memcpy(chunk.chChunkID, tag, 4);

    chunk.nChunkSize = sizeof(WAVEFORMATX);

    fwrite(&chunk, 1, sizeof(XCHUNKHEADER), fpwave);

    memset(&wfx, 0, sizeof(WAVEFORMATX));

    wfx.nFormatTag = 1;

    wfx.nChannels = 2; //

    wfx.nSamplesPerSec = 44100; // 8khz

    wfx.nAvgBytesPerSec = 176400;

    wfx.nBlockAlign = 2;

    wfx.nBitsPerSample = 16; // 16λ

    fwrite(&wfx, 1, sizeof(WAVEFORMATX), fpwave);

    // 3. ÐŽdata¿éÍ·

    strcpy(tag, "data");

    memcpy(chunk.chChunkID, tag, 4);

    //chunk.nChunkSize = 2319*18432*sizeof(char);

    chunk.nChunkSize = len*sizeof(char);

    fwrite(&chunk, 1, sizeof(XCHUNKHEADER), fpwave);
}

int  main(int argc, char *argv[])
{
    char * file_path="/home/lost/Desktop/test.ape";

    char * out_file_path="/home/lost/Desktop/456.wav";
    AVFormatContext *pFormatCtx;
    int i;
    int len;
    AVCodecContext *pCodecCtx;
    AVCodec *pCodec;
      AVPacket packet;
      uint8_t *  decompressed_audio_buf;
    int        videoStream=-1;
    int        audioStream = -1;
    FILE * file_out;
    int sample_len = 0;

    // Open video file
    av_register_all();
    if(av_open_input_file(&pFormatCtx,file_path , NULL, 0, NULL)!=0)
    {
        printf("Open error/n");
        return -1; // Couldn't open file
    }
    // Retrieve stream information
    if(av_find_stream_info(pFormatCtx)<0)
    {
        printf("Find info error/n");
        return -1; // Couldn't find stream informatio
    }
    // Dump information about file onto standard error

    dump_format(pFormatCtx, 0,file_path, 0);
    // Find the first video stream
    for(i=0; i<pFormatCtx->nb_streams; i++)
        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
            videoStream=i;
            break;
        }
    if(videoStream==-1)
    {
        printf("can not find a vedio stream/n");
        //return -1; // Didn't find a video stream
    }   
    for(i=0; i<pFormatCtx->nb_streams; i++)
        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
            audioStream=i;
            break;
        }
        if(audioStream==-1)
        {
            printf("can not find a audio stream/n");
            //return -1; // Didn't find a video stream
        }   
        // Get a pointer to the codec context for the audio stream
    pCodecCtx=pFormatCtx->streams[audioStream]->codec;
    // Find the decoder for the audio stream
    pCodec = avcodec_find_decoder (pCodecCtx->codec_id);
    if (pCodec == NULL)
    {
        printf("Can not find the codec/n");
        return -1;    // Codec not found
    }

    // Open codec
    if (avcodec_open (pCodecCtx, pCodec) < 0){
        printf("Open codec failed/n");
        return -1;    // Could not open codec
    }

    printf ("pCodecCtx->sample_rate:%d, audioStream:%d/n", (pCodecCtx)->sample_rate, audioStream);

    file_out = fopen(out_file_path,"wb");

    WriteWAVEFileHeader(file_out,0);

    i = 0;

     decompressed_audio_buf= malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);

     len = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;
    //len = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;

     av_init_packet(&packet);
    int len_not_codec =0;
    char * data;

    while (av_read_frame(pFormatCtx, &packet) >= 0)
    {
            //printf("haha,packet size = %d/n", packet.size);
            len_not_codec = packet.size;
            data = packet.data;

            while (len_not_codec>0) {
                len = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;
                i = avcodec_decode_audio2(pCodecCtx, (int16_t *)decompressed_audio_buf,  &len,data,len_not_codec );
                printf("haha,frame size = %d/n,packet skip %d", len,i);

                if(i<0)
                {
                    printf("error skip/n");
                    break;
                }

                data += i;
                len_not_codec -= i;

                if(len<0)
                {
                    printf("not data ,skip/n");
                    continue;
                }

                fwrite((char *)decompressed_audio_buf, 1, len, file_out);
            }
            if(packet.data)
                 av_free_packet(&packet);
    }

    avcodec_close(pCodecCtx);
    av_close_input_file(pFormatCtx);
    fseek(file_out,0,SEEK_SET);
    WriteWAVEFileHeader(file_out,sample_len);
    fclose(file_out);
    printf("haha/n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值