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]