-
Notifications
You must be signed in to change notification settings - Fork 45
/
demuxer.cpp
99 lines (71 loc) · 3.43 KB
/
demuxer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "demuxer.h"
#include <iostream>
#include "ffmpeg.h"
#include "string_utils.h"
Demuxer::Demuxer(const std::string& demuxer_name, const std::string& file_name, AVDictionary* demuxer_options, const AVDictionary* decoder_options) {
const AVInputFormat* input_format = nullptr;
if (!demuxer_name.empty()) {
input_format = av_find_input_format(demuxer_name.c_str());
if (input_format == nullptr) {
throw std::runtime_error(file_name + ": Demuxer '" + demuxer_name + "' not found");
}
}
ffmpeg::check(file_name, avformat_open_input(&format_context_, file_name.c_str(), const_cast<AVInputFormat*>(input_format), &demuxer_options));
ffmpeg::check_dict_is_empty(demuxer_options, string_sprintf("Demuxer %s", format_name().c_str()));
video_stream_index_ = ffmpeg::check(file_name, av_find_best_stream(format_context_, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0));
AVDictionary* stream_codec_options = nullptr;
av_dict_copy(&stream_codec_options, decoder_options, 0);
AVDictionary** opts_for_streams = (AVDictionary**)av_calloc(format_context_->nb_streams, sizeof(AVDictionary*));
opts_for_streams[video_stream_index_] = stream_codec_options;
ffmpeg::check(file_name, avformat_find_stream_info(format_context_, opts_for_streams));
}
Demuxer::~Demuxer() {
avformat_close_input(&format_context_);
}
AVCodecParameters* Demuxer::video_codec_parameters() {
return format_context_->streams[video_stream_index_]->codecpar;
}
int Demuxer::video_stream_index() const {
return video_stream_index_;
}
AVRational Demuxer::time_base() const {
return format_context_->streams[video_stream_index_]->time_base;
}
int64_t Demuxer::duration() const {
// use stream duration if available, otherwise use container duration if available, else 0
const int64_t stream_duration = format_context_->streams[video_stream_index_]->duration;
return stream_duration != AV_NOPTS_VALUE ? av_rescale_q(stream_duration, time_base(), AV_R_MICROSECONDS) : (format_context_->duration != AV_NOPTS_VALUE ? format_context_->duration : 0);
}
int64_t Demuxer::start_time() const {
return format_context_->start_time != AV_NOPTS_VALUE ? format_context_->start_time : 0;
}
int Demuxer::rotation() const {
double theta = 0;
uint8_t* displaymatrix = av_stream_get_side_data(format_context_->streams[video_stream_index_], AV_PKT_DATA_DISPLAYMATRIX, nullptr);
if (displaymatrix != nullptr) {
theta = -av_display_rotation_get(reinterpret_cast<int32_t*>(displaymatrix));
}
theta -= 360 * floor(theta / 360 + 0.9 / 360);
return theta;
}
AVRational Demuxer::guess_frame_rate(AVFrame* frame) const {
return av_guess_frame_rate(format_context_, format_context_->streams[video_stream_index_], frame);
}
bool Demuxer::operator()(AVPacket& packet) {
return av_read_frame(format_context_, &packet) >= 0;
}
bool Demuxer::seek(const float position, const bool backward) {
int64_t seek_target = static_cast<int64_t>(position * AV_TIME_BASE);
return av_seek_frame(format_context_, -1, seek_target, backward ? AVSEEK_FLAG_BACKWARD : 0) >= 0;
}
std::string Demuxer::format_name() {
return format_context_->iformat->name;
}
int64_t Demuxer::file_size() {
return avio_size(format_context_->pb);
}
int64_t Demuxer::bit_rate() {
// use stream bit rate if available, otherwise use container bit rate
const int64_t stream_bit_rate = format_context_->streams[video_stream_index_]->codecpar->bit_rate;
return stream_bit_rate > 0 ? stream_bit_rate : format_context_->bit_rate;
}