ffmpeg 4.2.4 

 源代码

extern "C"
{
    #include "libavformat/avformat.h"
    #include "libavcodec/avcodec.h"
    #include "libswscale/swscale.h"
    #include "libswresample/swresample.h"
    #include "libavfilter/avfilter.h"
    #include "libavfilter/buffersink.h"
    #include "libavfilter/buffersrc.h"
    #include "libavutil/error.h"
    #include "libavutil/rational.h"
}


#include <iostream>
#include <fstream>
#include <cassert>
#include <cstring>
#include <csignal>


bool g_bStop = false;

void on_ctrl_c(int ) 
{
    g_bStop = true;
}

void list_demuxer()
{
    void* opaque = nullptr;
    const AVInputFormat* pIFormat = av_demuxer_iterate(&opaque);
    while (pIFormat != nullptr)
    {
        std::cout << "" << pIFormat->name << std::endl;
        pIFormat = av_demuxer_iterate(&opaque);
    }
}

void read_file(const char* szFilename)
{
    do 
    {
        std::fstream fs;
        fs.open(szFilename, std::fstream::in | std::fstream::binary);
        if (!fs.is_open())
        {
            std::cout << "open file failed" << std::endl;
            break;
        }
        char buffer[1024] = "";
        for (int i = 0;; i++)
        {
            fs.read(buffer, 1024);
            auto iReadLength = fs.gcount();
            if(fs.eof()) break;
        }
        fs.close();
    } while (false);

}

// Entry
int main(int argc, char** argv)
{
    int iRet = 0;

    std::cout << "Start ." << std::endl;
    signal(SIGINT, &on_ctrl_c);

#if 0
    list_demuxer();
    read_file("normal.h264");
#endif
    
    std::string szMediaFilename = argc > 1 ? argv[1] : "normal.mp4";
    std::string szPrefixMediaFilename = szMediaFilename.substr(0, szMediaFilename.rfind('.'));
    char szErrorBuffer[AV_ERROR_MAX_STRING_SIZE] = "";
    AVFormatContext* pMediaFormatCtx = nullptr;
    
    do
    {
        // AVFormatContext
        iRet = avformat_open_input(&pMediaFormatCtx, szMediaFilename.c_str(), 0, 0);
        if(iRet != 0) 
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avformat_open_input failed " << szErrorBuffer << std::endl;
            break;
        }
        iRet = avformat_find_stream_info(pMediaFormatCtx, 0);
        if (iRet != 0)
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avformat_find_stream_info failed " << szErrorBuffer << std::endl;
            break;
        }
        // AVStream
        AVStream* pVideoStream = nullptr,* pAudioStream = nullptr;
        for (unsigned int i = 0; i < pMediaFormatCtx->nb_streams; i++)
        {
            if (pMediaFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                pVideoStream = pMediaFormatCtx->streams[i];
            }
            if (pMediaFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
            {
                pAudioStream = pMediaFormatCtx->streams[i];
            }
        }
        if (pVideoStream == nullptr)
        {
            std::cout << "pVideoStream empty " << std::endl;
            break;
        }
        if (pAudioStream == nullptr)
        {
            std::cout << "pAudioStream empty " << std::endl;
            break;
        }
        // AVCodecContext
        AVCodec* pVideoCodec = avcodec_find_decoder(pVideoStream->codecpar->codec_id);
        if (pVideoCodec == nullptr)
        {
            std::cout << "avcodec_find_decoder failed " << std::endl;
            break;
        }
        AVCodecContext* pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
        if (pVideoCodecCtx == nullptr)
        {
            std::cout << "avcodec_alloc_context3 failed " << std::endl;
            break;
        }
        iRet = avcodec_parameters_to_context(pVideoCodecCtx, pVideoStream->codecpar);
        if (iRet < 0)
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avcodec_parameters_to_context failed " << szErrorBuffer << std::endl;
            break;
        }
        AVCodec* pAudioCodec = avcodec_find_decoder(pAudioStream->codecpar->codec_id);
        if (pAudioCodec == nullptr)
        {
            std::cout << "avcodec_find_decoder failed " << std::endl;
            break;
        }
        AVCodecContext* pAudioCodecCtx = avcodec_alloc_context3(pAudioCodec);
        if (pAudioCodecCtx == nullptr)
        {
            std::cout << "avcodec_alloc_context3 failed " << std::endl;
            break;
        }
        iRet = avcodec_parameters_to_context(pAudioCodecCtx, pAudioStream->codecpar);
        if (iRet < 0)
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avcodec_parameters_to_context failed " << szErrorBuffer << std::endl;
            break;
        }
        // open decoder
        iRet = avcodec_open2(pVideoCodecCtx, pVideoCodec, nullptr);
        if(iRet != 0)
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avcodec_open2 failed " << szErrorBuffer << std::endl;
        }
        iRet = avcodec_open2(pAudioCodecCtx, pAudioCodec, nullptr);
        if (iRet != 0)
        {
            av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
            std::cout << "avcodec_open2 failed " << szErrorBuffer << std::endl;
        }
        // decode 
        AVPacket sMediapacket;
        AVFrame* pMediaFrame = av_frame_alloc();
        std::fstream videostream, audiostream;
        std::fstream videobigstream, audiobigstream;

        do
        {
            iRet = av_read_frame(pMediaFormatCtx, &sMediapacket);
            if (iRet < 0)
            {
                av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
                std::cout << "av_read_frame failed " << szErrorBuffer << std::endl;
                break;
            }
            if (sMediapacket.pts < 0)
            {
                std::cout << "avpacket pts: " << sMediapacket.pts << std::endl;
                continue;
            }
            // video decode
            if (sMediapacket.stream_index == pVideoStream->index)
            {
                iRet = avcodec_send_packet(pVideoCodecCtx, &sMediapacket);
                if (iRet != 0)
                {
                    av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
                    std::cout << "warning avcodec_send_packet failed " << szErrorBuffer << std::endl;
                    break;
                }
                iRet = avcodec_receive_frame(pVideoCodecCtx, pMediaFrame);
                if (iRet != 0)
                {
                    av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
                    std::cout << "warning avcodec_receive_frame failed " << szErrorBuffer << std::endl;
                    break;
                }
                // write h264 stream
                if(pVideoCodecCtx->codec_id == AV_CODEC_ID_H264)
                {
                    char szStart3Code[3] = { 0x00,0x00, 0x01 };
                    char szStart4Code[4] = { 0x00,0x00, 0x00, 0x01 };
                    if (!videostream.is_open())
                    {
                        videostream.open((szPrefixMediaFilename + ".h264").c_str(), std::fstream::out | std::fstream::binary);
                    }
                    assert(videostream.is_open());
                    videostream.seekg(0, std::fstream::end);
                    int iFileLength = (int)videostream.tellg();
                    videostream.seekg(0, std::fstream::cur);
                    // 0x67 SPS - 0x68 PPS nal unit
                    if (iFileLength == 0)
                    {
                        unsigned short u16SpsLength = (((unsigned short)pVideoCodecCtx->extradata[6]) << 8) + pVideoCodecCtx->extradata[7];
                        unsigned short u16PpsLength = (((unsigned short)pVideoCodecCtx->extradata[8 + u16SpsLength + 1]) << 8) + pVideoCodecCtx->extradata[9 + u16SpsLength + 1];
                        char* szSps = (char*)malloc(u16SpsLength);
                        char* szPps = (char*)malloc(u16PpsLength);
                        memcpy(szSps, (void*)&pVideoCodecCtx->extradata[6+2], u16SpsLength);
                        memcpy(szPps, (void*)&pVideoCodecCtx->extradata[6 + 2 + u16SpsLength + 1 + 2], u16PpsLength);
                        videostream.write(szStart4Code, 4);
                        videostream.write(szSps, u16SpsLength);
                        videostream.write(szStart4Code, 4);
                        videostream.write(szPps, u16PpsLength);
                        free(szSps);
                        free(szPps);
                    }
                    // other nal unit
                    for (int i = 0, iStep = 0; i < sMediapacket.size; i += iStep)
                    {
                        uint32_t iUnitSize = ((uint32_t)sMediapacket.data[i] << 24) + ((uint32_t)sMediapacket.data[i + 1] << 16) + 
                                             ((uint32_t)sMediapacket.data[i + 2] << 8) + (uint32_t)sMediapacket.data[i + 3];
                        iStep = iUnitSize + 4;
                        sMediapacket.data[i] = sMediapacket.data[i + 1] = sMediapacket.data[i + 2] = 0x00;
                        sMediapacket.data[i + 3] = 0x01;
                        videostream.write((char*)&sMediapacket.data[i], (std::streamsize)iStep);
                        std::cout << "write to file : pts  " << sMediapacket.pts * av_q2d(pVideoStream->time_base) << " size " << iStep << std::endl;
                    }
                }
            }
            // audio decode
            if (sMediapacket.stream_index == pAudioStream->index)
            {
                iRet = avcodec_send_packet(pAudioCodecCtx, &sMediapacket);
                if (iRet != 0)
                {
                    av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
                    std::cout << "warning avcodec_send_packet failed " << szErrorBuffer << std::endl;
                    break;
                }
                iRet = avcodec_receive_frame(pAudioCodecCtx, pMediaFrame);
                if (iRet != 0)
                {
                    av_strerror(iRet, szErrorBuffer, AV_ERROR_MAX_STRING_SIZE);
                    std::cout << "warning avcodec_receive_frame failed " << szErrorBuffer << std::endl;
                    break;
                }
                // write aac stream
                if (pAudioCodecCtx->codec_id == AV_CODEC_ID_AAC)
                {
                    if (!audiostream.is_open())
                    {
                        audiostream.open((szPrefixMediaFilename + ".aac").c_str(), std::fstream::out | std::fstream::binary);
                    }
                    assert(audiostream.is_open());
                    int rates[] = { 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,-1,-1,-1 };
                    int iProfile = pAudioStream->codecpar->profile;
                    int iChannel = pAudioStream->codecpar->channels;
                    int iSamplerate = pAudioStream->codecpar->sample_rate;
                    int iSamplerateIndex = 0;
                    for (auto rate : rates)
                    {
                        if(iSamplerate == rate) break;
                        iSamplerateIndex++;
                    }
                    int iAdtsLength = 7;
                    char* pAdts = (char*)malloc(iAdtsLength * sizeof(char));
                    int iSize = sMediapacket.size + iAdtsLength;
                    pAdts[0] = (char)0xff;
                    pAdts[1] = (char)0xf1;
                    pAdts[2] = (((iProfile - 1) << 6) + (iSamplerateIndex << 2) + (iChannel >> 2));
                    pAdts[3] = (((iChannel & 3) << 6) + (iSize >> 11));
                    pAdts[4] = ((iSize & 0x7ff) >> 3);;
                    pAdts[5] = (((iSize & 7) << 5) + 0x1f);
                    pAdts[6] = (char)0xfc;
                    audiostream.write(pAdts, (std::streamsize)iAdtsLength);
                    audiostream.write((char*)sMediapacket.data, (std::streamsize)sMediapacket.size);
                    free(pAdts);
                }
                // write pcm stream
                if(false)
                {
                    if (!audiobigstream.is_open())
                    {
                        audiobigstream.open((szPrefixMediaFilename + ".pcm").c_str(), std::fstream::out | std::fstream::binary);
                    }
                    assert(audiobigstream.is_open());
                    int iChannel = pAudioStream->codecpar->channels;
                    audiobigstream.write((char*)&pMediaFrame->data[0], (std::streamsize)pMediaFrame->linesize[0] / iChannel);
                    //std::cout << "write to file : pts  " << sMediapacket.pts * av_q2d(pAudioStream->time_base) << " size " << sMediapacket.size << std::endl;
                }
            }
            av_packet_unref(&sMediapacket);
        } while (!g_bStop);

        if (videostream.is_open())
        {
            videostream.close();
        }
        if (audiostream.is_open())
        {
            audiostream.close();
        }
        if (audiobigstream.is_open())
        {
            audiobigstream.close();
        }
        av_frame_free(&pMediaFrame);
        av_packet_unref(&sMediapacket);
        // close decoder
        avcodec_close(pAudioCodecCtx);
        avcodec_close(pVideoCodecCtx);
        // AVCodecContext
        avcodec_free_context(&pAudioCodecCtx);
        pAudioCodecCtx = nullptr;
        avcodec_free_context(&pVideoCodecCtx);
        pVideoCodecCtx = nullptr;
        // AVFormatContext
        avformat_close_input(&pMediaFormatCtx);
        pMediaFormatCtx = nullptr;
    }while(false);

    std::cout << "End ." << std::endl;

    return iRet;
}

windows build

@echo off

pushd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools\"
call VsDevCmd.bat -arch=amd64
popd

cl /c /I. /Iffmpeg\include /DWIN32 /W3 /WX- /GS /GR /Zi /Od /MDd /EHsc /nologo main.cpp
link main.obj /LIBPATH:. /LIBPATH:.\ffmpeg\lib /DYNAMICBASE avformat.lib avcodec.lib avutil.lib /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /PDB:main.pdb /OUT:main.exe
pause

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐