FFmpegAVDemuxer
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]