FFmpegPlayer/Demuxer.cpp
2024-01-18 22:22:26 +08:00

67 lines
2.3 KiB
C++

#include "Demuxer.h"
#include "BoostLog.h"
extern "C" {
#include "libavformat/avformat.h"
}
static_assert(AVMEDIA_TYPE_VIDEO == Stream::Video, "enum value must same...");
Demuxer::Demuxer() {
m_context = avformat_alloc_context();
}
Demuxer::~Demuxer() {
m_exit = true;
if (m_thread.joinable()) m_thread.join();
}
void Demuxer::open(const std::string &path) {
avformat_open_input(&m_context, path.c_str(), nullptr, nullptr);
av_dump_format(m_context, 0, path.c_str(), 0);
const AVCodec *videoCodec = nullptr, *audioCodec = nullptr;
m_streams[Stream::Video] = av_find_best_stream(m_context, AVMEDIA_TYPE_VIDEO, -1, -1, &videoCodec, 0);
m_streams[Stream::Audio] = av_find_best_stream(m_context, AVMEDIA_TYPE_AUDIO, -1, -1, &audioCodec, 0);
LOG(info) << "video stream index: " << m_streams[Stream::Video]
<< ", audio stream index: " << m_streams[Stream::Audio];
m_codecInformations[Stream::Video] = {videoCodec, m_context->streams[Stream::Video]->codecpar};
m_codecInformations[Stream::Audio] =
std::pair<const AVCodec *, const AVCodecParameters *>(audioCodec, m_context->streams[Stream::Audio]->codecpar);
}
Demuxer::CodecInformation Demuxer::codecInformation(Stream type) const {
return m_codecInformations[type];
}
void Demuxer::setStreamPacketCallback(Stream type, const Callback &callback) {
m_callback[type] = callback;
}
void Demuxer::start() {
m_exit = false;
m_thread = std::thread(&Demuxer::run, this);
}
void Demuxer::run() {
auto packet = av_packet_alloc();
while (!m_exit) {
int ret = av_read_frame(m_context, packet);
if (ret == AVERROR_EOF) {
LOG(info) << "end of file.";
break;
} else if (ret < 0) {
char buffer[AV_ERROR_MAX_STRING_SIZE] = {0};
av_strerror(ret, buffer, sizeof(buffer));
LOG(error) << "read failed: " << ret << ", " << buffer;
break;
}
std::shared_ptr<AVPacket> out(av_packet_alloc(), [](AVPacket *packet) { av_packet_free(&packet); });
av_packet_ref(out.get(), packet);
if (m_callback[packet->stream_index]) m_callback[packet->stream_index](out);
// LOG(info) << ". " << packet->stream_index;
av_packet_unref(packet);
}
av_packet_free(&packet);
}