Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

FFmpegAVDemuxer is a demuxer dependent on FFmpeg lib, which can demux media files into independent video and audio streams. Currently, only demux MP4/FMP4 is supported, and we will add support for more types of files in the future.

API Instructions

namespace com { namespace sunplus { namespace media {

using VideoDataCallback = std::function<void(AVPacket* packet, int index)>;
using AudioDataCallback = std::function<void(AVPacket* packet, int index)>;

class FFmpegAVDemuxer {
public:
    FFmpegAVDemuxer();
    ~FFmpegAVDemuxer();

public:
    int init(std::string filepath, VideoDataCallback videoCb, AudioDataCallback audioCb);
    void uninit();

    AVStream* getVideoStream();
    AVStream* getAudioStream();

	int getNextFrame();
};
}}}

Constructors

FFmpegAVDemuxer();

init

Open the file to demux, and retrieve stream information.

/**
 * initialize demuxer.
 *
 * @param filepath the file to demux.
 *
 * @param videoCb to get video packet.
 *
 * @param audioCb to get audio packet.
 *
 * @return 0 if OK, < 0 on error. 
 */
int init(std::string filepath, VideoDataCallback videoCb, AudioDataCallback audioCb);

uninit

Release all resources allocated by the init method and close the file.

/**
 * Release all resources allocated by the init method.
 */
void uninit();

getVideoStream

You can get video stream information through it, but it must be after the demuxer is successfully init. Such as gop, fps, bitrate, duration, etc.

/**
 * Get the AVStream for AVFormatContext, It can be used to get video stream information. 
 * Such as time_base, start_time, codec, etc.
 */
AVStream* getVideoStream();

Sample

auto demuxer = make_shared<FFmpegAVDemuxer>();
//init demuxer
......
// get video stream info
auto videoStream = demuxer->getVideoStream();
auto videoCodecCtx = this->videoStream->codec;
printf("videoStream, width: %d, height: %d\n", videoStream->codecpar->width, videoStream->codecpar->height);
printf("videoStream, fps: %d/%d\n", videoStream->r_frame_rate.num, videoStream->r_frame_rate.den);
printf("videoStream, gop: %d\n", videoCodecCtx->gop_size);
printf("videoStream, bitrate: %d\n", videoCodecCtx->bit_rate);
printf("videoStream, duration: %d\n", videoStream->duration);
printf("videoStream, duration ms: %d\n", av_ts_make_time_ms(videoStream->duration, &videoStream->time_base));

getAudioStream

You can get audio stream information through it, but it must be after the demuxer is successfully init. Such as sample_rate, channels, bitrate, duration, etc.

/**
 * Get the AVStream for AVFormatContext, It can be used get audio stream information. 
 * Such as sample_rate, channels, bitrate, duration, etc.
 */
AVStream* getAudioStream();

Sample

auto demuxer = make_shared<FFmpegAVDemuxer>();
//init demuxer
......
// get audio stream info
auto audioStream = demuxer->getAudioStream();
auto audioCodecCtx = this->audioStream->codec;
printf("audioStream, sample rate: %d\n", audioCodecCtx->sample_rate);
printf("audioStream, channels: %d\n", audioCodecCtx->channels);
printf("audioStream, bits_per_raw_sample: %d\n", audioCodecCtx->bits_per_raw_sample);
printf("audioStream, bitrate: %d\n", audioCodecCtx->bit_rate);
printf("audioStream, duration: %d\n", audioStream->duration);
printf("audioStream, duration ms: %d\n", av_ts_make_time_ms(audioStream->duration, &audioStream->time_base));

getNextFrame

Get the next frame of the file. The frame is returned through VideoDataCallback and AudioDataCallback.

/**
 * Get the next frame of the file.
 * The frame is returned through VideoDataCallback and AudioDataCallback.
 * @return 0 if OK, < 0 on error. 
 *         AVERROR_EOF: end of file
 */
int getNextFrame();

Sample Code

This is a sample of demux the MP4 file.

the flow of demux:

create demuxer --> init demuxer --> create the thread of get frame --> end of file --> uninit demuxer

void FFmpegMP4Demuxer_Test(const char* path) {
    string filepath = "ffmpeg_mp4_muxer_test.mp4";
    if (path != nullptr) {
        filepath = string(path);
    }
    
    FILE* h264file = fopen("ffmpeg_mp4_demux_test.h264", "wb+");
    FILE* aacfile = fopen("ffmpeg_mp4_demux_test.aac", "wb+");

    auto mp4Demuxer = make_shared<FFmpegAVDemuxer>();

    auto videoCallback = [&](AVPacket* packet, int index){
        printf("VideoDataCallback, h264 frame[%d] pts: %lld, size: %d, isKeyFrame: %d\n", index, packet->pts, packet->size, packet->flags & AV_PKT_FLAG_KEY);
        fwrite(packet->data, packet->size, 1, h264file);
    };

    auto audioCallback = [&](AVPacket* packet, int index){
        printf("AudioDataCallback, aac frame[%d] pts: %lld, size: %d\n", index, packet->pts, packet->size);
        fwrite(packet->data, packet->size, 1, aacfile);
    };

    int ret = mp4Demuxer->init(filepath, videoCallback, audioCallback);

    while(1) {
        int ret = mp4Demuxer->getNextFrame();
        if (ret < 0) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            break;
        }
    }

    fclose(h264file);
    fclose(aacfile);

    mp4Demuxer->uninit();
}

Test Result

./ffmpeg_sample mp4demux [filepath]
FFmpegAVDemuxerTestResult.png

  • No labels