67 lines
2.3 KiB
C++
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);
|
|
}
|