mirror of
https://github.com/steredbits/pelagia.git
synced 2026-10-17 21:01:34 +02:00
81 lines
2.1 KiB
C++
81 lines
2.1 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2026 steredbits and Pelagia contributors
|
|
#include "player/media_source.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
namespace player {
|
|
|
|
bool MediaSource::stream_info(AVMediaType type, AVCodecParameters* par, AVRational* time_base,
|
|
AVRational* frame_rate) {
|
|
AVFormatContext* ctx = format_context();
|
|
if (!ctx) {
|
|
return false;
|
|
}
|
|
const int index = av_find_best_stream(ctx, type, -1, -1, nullptr, 0);
|
|
if (index < 0 || avcodec_parameters_copy(par, ctx->streams[index]->codecpar) < 0) {
|
|
return false;
|
|
}
|
|
*time_base = ctx->streams[index]->time_base;
|
|
*frame_rate = ctx->streams[index]->avg_frame_rate;
|
|
return true;
|
|
}
|
|
|
|
bool FileSource::open() {
|
|
if (ctx_) {
|
|
return true;
|
|
}
|
|
int err = avformat_open_input(&ctx_, path_, nullptr, nullptr);
|
|
if (err < 0) {
|
|
char buf[128];
|
|
av_strerror(err, buf, sizeof(buf));
|
|
LOG_ERROR("FileSource: cannot open '%s': %s", path_, buf);
|
|
return false;
|
|
}
|
|
err = avformat_find_stream_info(ctx_, nullptr);
|
|
if (err < 0) {
|
|
LOG_ERROR("FileSource: unreadable streams in '%s' (err=%d)", path_, err);
|
|
avformat_close_input(&ctx_);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void FileSource::close() {
|
|
if (ctx_) {
|
|
avformat_close_input(&ctx_);
|
|
}
|
|
}
|
|
|
|
int FileSource::read(AVPacket* pkt) {
|
|
return av_read_frame(ctx_, pkt);
|
|
}
|
|
|
|
bool FileSource::seek(int64_t target_ms) {
|
|
// Keyframe preceding the target: the decoder restarts cleanly.
|
|
const int64_t ts = target_ms * (AV_TIME_BASE / 1000);
|
|
const int err = av_seek_frame(ctx_, -1, ts, AVSEEK_FLAG_BACKWARD);
|
|
if (err < 0) {
|
|
LOG_WARN("FileSource: seek to %lld ms refused (err=%d)",
|
|
static_cast<long long>(target_ms), err);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int64_t FileSource::duration_ms() const {
|
|
if (!ctx_ || ctx_->duration == AV_NOPTS_VALUE) {
|
|
return 0;
|
|
}
|
|
return ctx_->duration / (AV_TIME_BASE / 1000);
|
|
}
|
|
|
|
int64_t FileSource::start_time_ms() const {
|
|
if (!ctx_ || ctx_->start_time == AV_NOPTS_VALUE) {
|
|
return 0;
|
|
}
|
|
return ctx_->start_time / (AV_TIME_BASE / 1000);
|
|
}
|
|
|
|
} // namespace player
|