Unified class methods naming (lower case function names as other

classes)
This commit is contained in:
brunoherbelin
2020-04-03 23:06:24 +02:00
parent fc256693dc
commit 0e25810a74
4 changed files with 295 additions and 278 deletions

6
FrameBuffer.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "FrameBuffer.h"
FrameBuffer::FrameBuffer()
{
}

11
FrameBuffer.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
class FrameBuffer
{
public:
FrameBuffer();
};
#endif // FRAMEBUFFER_H

View File

@@ -40,41 +40,41 @@ GLuint blackTexture()
return tex_index_black; return tex_index_black;
} }
MediaPlayer::MediaPlayer(string name) : id(name) MediaPlayer::MediaPlayer(string name) : id_(name)
{ {
if (std::empty(id)) if (std::empty(id_))
id = GstToolkit::date_time_string(); id_ = GstToolkit::date_time_string();
uri = "undefined"; uri_ = "undefined";
pipeline = nullptr; pipeline_ = nullptr;
discoverer = nullptr; discoverer_ = nullptr;
ready = false; ready_ = false;
seekable = false; seekable_ = false;
isimage = false; isimage_ = false;
interlaced = false; interlaced_ = false;
need_loop = false; need_loop_ = false;
v_frame_is_full = false; v_frame_is_full_ = false;
rate = 1.0; rate_ = 1.0;
framerate = 0.0; framerate_ = 0.0;
width = par_width = 640; width_ = par_width_ = 640;
height = 480; height_ = 480;
position = GST_CLOCK_TIME_NONE; position_ = GST_CLOCK_TIME_NONE;
duration = GST_CLOCK_TIME_NONE; duration_ = GST_CLOCK_TIME_NONE;
start_position = GST_CLOCK_TIME_NONE; start_position_ = GST_CLOCK_TIME_NONE;
frame_duration = GST_CLOCK_TIME_NONE; frame_duration_ = GST_CLOCK_TIME_NONE;
desired_state = GST_STATE_PAUSED; desired_state_ = GST_STATE_PAUSED;
loop = LoopMode::LOOP_REWIND; loop_ = LoopMode::LOOP_REWIND;
current_segment = segments.begin(); current_segment_ = segments_.begin();
v_frame.buffer = nullptr; v_frame_.buffer = nullptr;
textureindex = 0; textureindex_ = 0;
} }
MediaPlayer::~MediaPlayer() MediaPlayer::~MediaPlayer()
{ {
Close(); close();
// g_free(v_frame); // g_free(v_frame);
} }
@@ -82,48 +82,48 @@ void MediaPlayer::accept(Visitor& v) {
v.visit(*this); v.visit(*this);
} }
void MediaPlayer::Bind() void MediaPlayer::bind()
{ {
glBindTexture(GL_TEXTURE_2D, Texture()); glBindTexture(GL_TEXTURE_2D, texture());
} }
guint MediaPlayer::Texture() const guint MediaPlayer::texture() const
{ {
if (textureindex == 0) if (textureindex_ == 0)
return blackTexture(); return blackTexture();
return textureindex; return textureindex_;
} }
void MediaPlayer::Open(string uri) void MediaPlayer::open(string uri)
{ {
// set uri to open // set uri to open
this->uri = uri; this->uri_ = uri;
// reset // reset
ready = false; ready_ = false;
/* Instantiate the Discoverer */ /* Instantiate the Discoverer */
GError *err = NULL; GError *err = NULL;
discoverer = gst_discoverer_new (5 * GST_SECOND, &err); discoverer_ = gst_discoverer_new (5 * GST_SECOND, &err);
if (!discoverer) { if (!discoverer_) {
Log::Warning("MediaPlayer Error creating discoverer instance: %s\n", err->message); Log::Warning("MediaPlayer Error creating discoverer instance: %s\n", err->message);
g_clear_error (&err); g_clear_error (&err);
return; return;
} }
// set callback for filling in information into this MediaPlayer // set callback for filling in information into this MediaPlayer
g_signal_connect (discoverer, "discovered", G_CALLBACK (callback_discoverer_process), this); g_signal_connect (discoverer_, "discovered", G_CALLBACK (callback_discoverer_process), this);
// set callback when finished discovering // set callback when finished discovering
g_signal_connect (discoverer, "finished", G_CALLBACK (callback_discoverer_finished), this); g_signal_connect (discoverer_, "finished", G_CALLBACK (callback_discoverer_finished), this);
// start discoverer // start discoverer
gst_discoverer_start(discoverer); gst_discoverer_start(discoverer_);
// Add the request to process asynchronously the URI // Add the request to process asynchronously the URI
if (!gst_discoverer_discover_uri_async (discoverer, uri.c_str())) { if (!gst_discoverer_discover_uri_async (discoverer_, uri.c_str())) {
Log::Warning("MediaPlayer %s Failed to start discovering URI '%s'\n", id.c_str(), uri.c_str()); Log::Warning("MediaPlayer %s Failed to start discovering URI '%s'\n", id_.c_str(), uri.c_str());
g_object_unref (discoverer); g_object_unref (discoverer_);
discoverer = nullptr; discoverer_ = nullptr;
} }
// and wait for discoverer to finish... // and wait for discoverer to finish...
@@ -133,31 +133,31 @@ void MediaPlayer::Open(string uri)
void MediaPlayer::execute_open() void MediaPlayer::execute_open()
{ {
// build string describing pipeline // build string describing pipeline
string description = "uridecodebin uri=" + uri + " name=decoder !"; string description = "uridecodebin uri=" + uri_ + " name=decoder !";
if (interlaced) if (interlaced_)
description += " deinterlace !"; description += " deinterlace !";
description += " videoconvert ! appsink name=sink"; description += " videoconvert ! appsink name=sink";
// parse pipeline descriptor // parse pipeline descriptor
GError *error = NULL; GError *error = NULL;
pipeline = gst_parse_launch (description.c_str(), &error); pipeline_ = gst_parse_launch (description.c_str(), &error);
if (error != NULL) { if (error != NULL) {
Log::Warning("MediaPlayer %s Could not construct pipeline %s:\n%s", id.c_str(), description.c_str(), error->message); Log::Warning("MediaPlayer %s Could not construct pipeline %s:\n%s", id_.c_str(), description.c_str(), error->message);
g_clear_error (&error); g_clear_error (&error);
return; return;
} }
g_object_set(G_OBJECT(pipeline), "name", id.c_str(), NULL); g_object_set(G_OBJECT(pipeline_), "name", id_.c_str(), NULL);
// GstCaps *caps = gst_static_caps_get (&frame_render_caps); // GstCaps *caps = gst_static_caps_get (&frame_render_caps);
string capstring = "video/x-raw,format=RGBA,width="+ std::to_string(width) + ",height=" + std::to_string(height); string capstring = "video/x-raw,format=RGBA,width="+ std::to_string(width_) + ",height=" + std::to_string(height_);
GstCaps *caps = gst_caps_from_string(capstring.c_str()); GstCaps *caps = gst_caps_from_string(capstring.c_str());
if (!gst_video_info_from_caps (&v_frame_video_info, caps)) { if (!gst_video_info_from_caps (&v_frame_video_info_, caps)) {
Log::Warning("MediaPlayer %s Could not configure video frame info", id.c_str()); Log::Warning("MediaPlayer %s Could not configure video frame info", id_.c_str());
return; return;
} }
// setup appsink // setup appsink
GstElement *sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); GstElement *sink = gst_bin_get_by_name (GST_BIN (pipeline_), "sink");
if (sink) { if (sink) {
// set all properties // set all properties
@@ -177,7 +177,7 @@ void MediaPlayer::execute_open()
gst_object_unref (sink); gst_object_unref (sink);
} }
else { else {
Log::Warning("MediaPlayer %s Could not configure sink", id.c_str()); Log::Warning("MediaPlayer %s Could not configure sink", id_.c_str());
return; return;
} }
gst_caps_unref (caps); gst_caps_unref (caps);
@@ -186,226 +186,226 @@ void MediaPlayer::execute_open()
//Rendering::LinkPipeline(GST_PIPELINE (pipeline)); //Rendering::LinkPipeline(GST_PIPELINE (pipeline));
// set to desired state (PLAY or PAUSE) // set to desired state (PLAY or PAUSE)
GstStateChangeReturn ret = gst_element_set_state (pipeline, desired_state); GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_);
if (ret == GST_STATE_CHANGE_FAILURE) { if (ret == GST_STATE_CHANGE_FAILURE) {
Log::Warning("MediaPlayer %s Could not open %s", id.c_str(), uri.c_str()); Log::Warning("MediaPlayer %s Could not open %s", id_.c_str(), uri_.c_str());
return; return;
} }
// all good // all good
Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id.c_str(), uri.c_str(), codec_name.c_str(), width, height); Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id_.c_str(), uri_.c_str(), codec_name_.c_str(), width_, height_);
ready = true; ready_ = true;
} }
bool MediaPlayer::isOpen() const bool MediaPlayer::isOpen() const
{ {
return ready; return ready_;
} }
void MediaPlayer::Close() void MediaPlayer::close()
{ {
// stop discovering stream // stop discovering stream
if (discoverer != nullptr) { if (discoverer_ != nullptr) {
gst_discoverer_stop (discoverer); gst_discoverer_stop (discoverer_);
g_object_unref (discoverer); g_object_unref (discoverer_);
discoverer = nullptr; discoverer_ = nullptr;
} }
if (!ready) if (!ready_)
return; return;
// clean up GST // clean up GST
if (pipeline != nullptr) { if (pipeline_ != nullptr) {
gst_element_set_state (pipeline, GST_STATE_NULL); gst_element_set_state (pipeline_, GST_STATE_NULL);
gst_object_unref (pipeline); gst_object_unref (pipeline_);
pipeline = nullptr; pipeline_ = nullptr;
} }
// nothing to display // nothing to display
textureindex = blackTexture(); textureindex_ = blackTexture();
// un-ready the media player // un-ready the media player
ready = false; ready_ = false;
} }
GstClockTime MediaPlayer::Duration() GstClockTime MediaPlayer::duration()
{ {
if (duration == GST_CLOCK_TIME_NONE && pipeline != nullptr) { if (duration_ == GST_CLOCK_TIME_NONE && pipeline_ != nullptr) {
gint64 d = GST_CLOCK_TIME_NONE; gint64 d = GST_CLOCK_TIME_NONE;
if ( gst_element_query_duration(pipeline, GST_FORMAT_TIME, &d) ) if ( gst_element_query_duration(pipeline_, GST_FORMAT_TIME, &d) )
duration = d; duration_ = d;
} }
return duration; return duration_;
} }
GstClockTime MediaPlayer::FrameDuration() GstClockTime MediaPlayer::frameDuration()
{ {
return frame_duration; return frame_duration_;
} }
guint MediaPlayer::Width() const guint MediaPlayer::width() const
{ {
return width; return width_;
} }
guint MediaPlayer::Height() const guint MediaPlayer::height() const
{ {
return height; return height_;
} }
float MediaPlayer::AspectRatio() const float MediaPlayer::aspectRatio() const
{ {
return static_cast<float>(par_width) / static_cast<float>(height); return static_cast<float>(par_width_) / static_cast<float>(height_);
} }
GstClockTime MediaPlayer::Position() GstClockTime MediaPlayer::position()
{ {
GstClockTime pos = position; GstClockTime pos = position_;
if (pos == GST_CLOCK_TIME_NONE && pipeline != nullptr) { if (pos == GST_CLOCK_TIME_NONE && pipeline_ != nullptr) {
gint64 p = GST_CLOCK_TIME_NONE; gint64 p = GST_CLOCK_TIME_NONE;
if ( gst_element_query_position (pipeline, GST_FORMAT_TIME, &p) ) if ( gst_element_query_position (pipeline_, GST_FORMAT_TIME, &p) )
pos = p; pos = p;
} }
return pos - start_position; return pos - start_position_;
} }
void MediaPlayer::Play(bool on) void MediaPlayer::play(bool on)
{ {
// cannot play an image // cannot play an image
if (isimage) if (isimage_)
return; return;
// request state // request state
GstState requested_state = on ? GST_STATE_PLAYING : GST_STATE_PAUSED; GstState requested_state = on ? GST_STATE_PLAYING : GST_STATE_PAUSED;
// ignore if requesting twice same state // ignore if requesting twice same state
if (desired_state == requested_state) if (desired_state_ == requested_state)
return; return;
// accept request to the desired state // accept request to the desired state
desired_state = requested_state; desired_state_ = requested_state;
// if not ready yet, the requested state will be handled later // if not ready yet, the requested state will be handled later
if ( pipeline == nullptr ) if ( pipeline_ == nullptr )
return; return;
// requesting to play, but stopped at end of stream : rewind first ! // requesting to play, but stopped at end of stream : rewind first !
if ( desired_state == GST_STATE_PLAYING) { if ( desired_state_ == GST_STATE_PLAYING) {
if ( ( rate>0.0 ? duration - Position() : Position() ) < 2 * frame_duration ) if ( ( rate_>0.0 ? duration_ - position() : position() ) < 2 * frame_duration_ )
Rewind(); rewind();
} }
// all ready, apply state change immediately // all ready, apply state change immediately
GstStateChangeReturn ret = gst_element_set_state (pipeline, desired_state); GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_);
if (ret == GST_STATE_CHANGE_FAILURE) { if (ret == GST_STATE_CHANGE_FAILURE) {
Log::Warning("MediaPlayer %s Failed to start", gst_element_get_name(pipeline)); Log::Warning("MediaPlayer %s Failed to start", gst_element_get_name(pipeline_));
} }
#ifdef MEDIA_PLAYER_DEBUG #ifdef MEDIA_PLAYER_DEBUG
else if (on) else if (on)
Log::Info("MediaPlayer %s Start", gst_element_get_name(pipeline)); Log::Info("MediaPlayer %s Start", gst_element_get_name(pipeline_));
else else
Log::Info("MediaPlayer %s Stop", gst_element_get_name(pipeline)); Log::Info("MediaPlayer %s Stop", gst_element_get_name(pipeline_));
#endif #endif
// reset time counter on stop // reset time counter on stop
if (!on) if (!on)
timecount.reset(); timecount_.reset();
} }
bool MediaPlayer::isPlaying() const bool MediaPlayer::isPlaying() const
{ {
// image cannot play // image cannot play
if (isimage) if (isimage_)
return false; return false;
// if not ready yet, answer with requested state // if not ready yet, answer with requested state
if ( pipeline == nullptr ) if ( pipeline_ == nullptr )
return desired_state == GST_STATE_PLAYING; return desired_state_ == GST_STATE_PLAYING;
// if ready, answer with actual state // if ready, answer with actual state
GstState state; GstState state;
gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE);
return state == GST_STATE_PLAYING; return state == GST_STATE_PLAYING;
// return desired_state == GST_STATE_PLAYING; // return desired_state == GST_STATE_PLAYING;
} }
MediaPlayer::LoopMode MediaPlayer::Loop() const MediaPlayer::LoopMode MediaPlayer::loop() const
{ {
return loop; return loop_;
} }
void MediaPlayer::setLoop(MediaPlayer::LoopMode mode) void MediaPlayer::setLoop(MediaPlayer::LoopMode mode)
{ {
loop = mode; loop_ = mode;
} }
void MediaPlayer::Rewind() void MediaPlayer::rewind()
{ {
if (!seekable) if (!seekable_)
return; return;
if (rate > 0.0) if (rate_ > 0.0)
// playing forward, loop to begin // playing forward, loop to begin
execute_seek_command(0); execute_seek_command(0);
else else
// playing backward, loop to end // playing backward, loop to end
execute_seek_command(duration); execute_seek_command(duration_);
} }
void MediaPlayer::SeekNextFrame() void MediaPlayer::seekNextFrame()
{ {
// useful only when Paused // useful only when Paused
if (isPlaying()) if (isPlaying())
return; return;
if ( loop != LOOP_NONE) { if ( loop_ != LOOP_NONE) {
// eventually loop if mode allows // eventually loop if mode allows
if ( ( rate>0.0 ? duration - Position() : Position() ) < 2 * frame_duration ) if ( ( rate_>0.0 ? duration_ - position() : position() ) < 2 * frame_duration_ )
need_loop = true; need_loop_ = true;
} }
// step // step
gst_element_send_event (pipeline, gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS(rate), TRUE, FALSE)); gst_element_send_event (pipeline_, gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS(rate_), TRUE, FALSE));
} }
void MediaPlayer::SeekTo(GstClockTime pos) void MediaPlayer::seekTo(GstClockTime pos)
{ {
if (!seekable) if (!seekable_)
return; return;
// remember pos // remember pos
GstClockTime previous_pos = Position(); GstClockTime previous_pos = position();
// apply seek // apply seek
GstClockTime target = CLAMP(pos, 0, duration); GstClockTime target = CLAMP(pos, 0, duration_);
execute_seek_command(target); execute_seek_command(target);
} }
void MediaPlayer::FastForward() void MediaPlayer::fastForward()
{ {
if (!seekable) if (!seekable_)
return; return;
double step = SIGN(rate) * 0.01 * static_cast<double>(duration); double step = SIGN(rate_) * 0.01 * static_cast<double>(duration_);
GstClockTime target = Position() + static_cast<GstClockTime>(step); GstClockTime target = position() + static_cast<GstClockTime>(step);
// manage loop // manage loop
if ( target > duration ) { if ( target > duration_ ) {
if (loop == LOOP_NONE) if (loop_ == LOOP_NONE)
target = duration; target = duration_;
else else
target = target - duration; target = target - duration_;
} }
SeekTo(target); seekTo(target);
} }
@@ -418,7 +418,7 @@ bool MediaPlayer::addPlaySegment(GstClockTime begin, GstClockTime end)
bool MediaPlayer::addPlaySegment(MediaSegment s) bool MediaPlayer::addPlaySegment(MediaSegment s)
{ {
if ( s.is_valid() ) if ( s.is_valid() )
return segments.insert(s).second; return segments_.insert(s).second;
return false; return false;
} }
@@ -431,10 +431,10 @@ bool MediaPlayer::removeAllPlaySegmentOverlap(MediaSegment s)
bool MediaPlayer::removePlaySegmentAt(GstClockTime t) bool MediaPlayer::removePlaySegmentAt(GstClockTime t)
{ {
MediaSegmentSet::const_iterator s = std::find_if(segments.begin(), segments.end(), containsTime(t)); MediaSegmentSet::const_iterator s = std::find_if(segments_.begin(), segments_.end(), containsTime(t));
if ( s != segments.end() ) { if ( s != segments_.end() ) {
segments.erase(s); segments_.erase(s);
return true; return true;
} }
@@ -444,70 +444,70 @@ bool MediaPlayer::removePlaySegmentAt(GstClockTime t)
std::list< std::pair<guint64, guint64> > MediaPlayer::getPlaySegments() const std::list< std::pair<guint64, guint64> > MediaPlayer::getPlaySegments() const
{ {
std::list< std::pair<guint64, guint64> > ret; std::list< std::pair<guint64, guint64> > ret;
for (MediaSegmentSet::iterator it = segments.begin(); it != segments.end(); it++) for (MediaSegmentSet::iterator it = segments_.begin(); it != segments_.end(); it++)
ret.push_back( std::make_pair( it->begin, it->end ) ); ret.push_back( std::make_pair( it->begin, it->end ) );
return ret; return ret;
} }
void MediaPlayer::Update() void MediaPlayer::update()
{ {
// discard // discard
if (!ready) if (!ready_)
return; return;
// done discovering stream // done discovering stream
if (discoverer != nullptr) { if (discoverer_ != nullptr) {
gst_discoverer_stop (discoverer); gst_discoverer_stop (discoverer_);
g_object_unref (discoverer); g_object_unref (discoverer_);
discoverer = nullptr; discoverer_ = nullptr;
} }
// apply texture // apply texture
if (v_frame_is_full) { if (v_frame_is_full_) {
// first occurence; create texture // first occurence; create texture
if (textureindex==0) { if (textureindex_==0) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &textureindex); glGenTextures(1, &textureindex_);
glBindTexture(GL_TEXTURE_2D, textureindex); glBindTexture(GL_TEXTURE_2D, textureindex_);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_,
0, GL_RGBA, GL_UNSIGNED_BYTE, v_frame.data[0]); 0, GL_RGBA, GL_UNSIGNED_BYTE, v_frame_.data[0]);
} }
else // bind texture else // bind texture
{ {
glBindTexture(GL_TEXTURE_2D, textureindex); glBindTexture(GL_TEXTURE_2D, textureindex_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_,
GL_RGBA, GL_UNSIGNED_BYTE, v_frame.data[0]); GL_RGBA, GL_UNSIGNED_BYTE, v_frame_.data[0]);
} }
// sync with callback_pull_last_sample_video // sync with callback_pull_last_sample_video
v_frame_is_full = false; v_frame_is_full_ = false;
} }
// manage loop mode // manage loop mode
if (need_loop && !isimage) { if (need_loop_ && !isimage_) {
execute_loop_command(); execute_loop_command();
need_loop = false; need_loop_ = false;
} }
// all other updates below are only for playing mode // all other updates below are only for playing mode
if (desired_state != GST_STATE_PLAYING) if (desired_state_ != GST_STATE_PLAYING)
return; return;
// test segments // test segments
if ( segments.begin() != segments.end()) { if ( segments_.begin() != segments_.end()) {
if ( current_segment == segments.end() ) if ( current_segment_ == segments_.end() )
current_segment = segments.begin(); current_segment_ = segments_.begin();
if ( Position() > current_segment->end) { if ( position() > current_segment_->end) {
g_print("switch to next segment "); g_print("switch to next segment ");
current_segment++; current_segment_++;
if ( current_segment == segments.end() ) if ( current_segment_ == segments_.end() )
current_segment = segments.begin(); current_segment_ = segments_.begin();
SeekTo(current_segment->begin); seekTo(current_segment_->begin);
} }
} }
@@ -516,21 +516,21 @@ void MediaPlayer::Update()
void MediaPlayer::execute_loop_command() void MediaPlayer::execute_loop_command()
{ {
if (loop==LOOP_REWIND) { if (loop_==LOOP_REWIND) {
Rewind(); rewind();
} }
else if (loop==LOOP_BIDIRECTIONAL) { else if (loop_==LOOP_BIDIRECTIONAL) {
rate *= - 1.f; rate_ *= - 1.f;
execute_seek_command(); execute_seek_command();
} }
else { else {
Play(false); play(false);
} }
} }
void MediaPlayer::execute_seek_command(GstClockTime target) void MediaPlayer::execute_seek_command(GstClockTime target)
{ {
if ( pipeline == nullptr || !seekable) if ( pipeline_ == nullptr || !seekable_)
return; return;
GstEvent *seek_event = nullptr; GstEvent *seek_event = nullptr;
@@ -541,12 +541,12 @@ void MediaPlayer::execute_seek_command(GstClockTime target)
// no target given // no target given
if (target == GST_CLOCK_TIME_NONE) if (target == GST_CLOCK_TIME_NONE)
// create seek event with current position (rate changed ?) // create seek event with current position (rate changed ?)
seek_pos = Position(); seek_pos = position();
// target is given but useless // target is given but useless
else if ( ABS_DIFF(target, Position()) < frame_duration) { else if ( ABS_DIFF(target, position()) < frame_duration_) {
// ignore request // ignore request
#ifdef MEDIA_PLAYER_DEBUG #ifdef MEDIA_PLAYER_DEBUG
Log::Info("MediaPlayer %s Ignored seek to current position", id.c_str()); Log::Info("MediaPlayer %s Ignored seek to current position", id_.c_str());
#endif #endif
return; return;
} }
@@ -554,61 +554,61 @@ void MediaPlayer::execute_seek_command(GstClockTime target)
// seek with flush (always) // seek with flush (always)
int seek_flags = GST_SEEK_FLAG_FLUSH; int seek_flags = GST_SEEK_FLAG_FLUSH;
// seek with trick mode if fast speed // seek with trick mode if fast speed
if ( ABS(rate) > 2.0 ) if ( ABS(rate_) > 2.0 )
seek_flags |= GST_SEEK_FLAG_TRICKMODE; seek_flags |= GST_SEEK_FLAG_TRICKMODE;
// create seek event depending on direction // create seek event depending on direction
if (rate > 0) { if (rate_ > 0) {
seek_event = gst_event_new_seek (rate, GST_FORMAT_TIME, (GstSeekFlags) seek_flags, seek_event = gst_event_new_seek (rate_, GST_FORMAT_TIME, (GstSeekFlags) seek_flags,
GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_END, 0); GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_END, 0);
} else { } else {
seek_event = gst_event_new_seek (rate, GST_FORMAT_TIME, (GstSeekFlags) seek_flags, seek_event = gst_event_new_seek (rate_, GST_FORMAT_TIME, (GstSeekFlags) seek_flags,
GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seek_pos); GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seek_pos);
} }
// Send the event (ASYNC) // Send the event (ASYNC)
if (seek_event && !gst_element_send_event(pipeline, seek_event) ) if (seek_event && !gst_element_send_event(pipeline_, seek_event) )
Log::Warning("MediaPlayer %s Seek failed", gst_element_get_name(pipeline)); Log::Warning("MediaPlayer %s Seek failed", gst_element_get_name(pipeline_));
#ifdef MEDIA_PLAYER_DEBUG #ifdef MEDIA_PLAYER_DEBUG
else else
Log::Info("MediaPlayer %s Seek %ld %f", gst_element_get_name(pipeline), seek_pos, rate); Log::Info("MediaPlayer %s Seek %ld %f", gst_element_get_name(pipeline_), seek_pos, rate_);
#endif #endif
} }
void MediaPlayer::SetPlaySpeed(double s) void MediaPlayer::setPlaySpeed(double s)
{ {
if (isimage) if (isimage_)
return; return;
// bound to interval [-MAX_PLAY_SPEED MAX_PLAY_SPEED] // bound to interval [-MAX_PLAY_SPEED MAX_PLAY_SPEED]
rate = CLAMP(s, -MAX_PLAY_SPEED, MAX_PLAY_SPEED); rate_ = CLAMP(s, -MAX_PLAY_SPEED, MAX_PLAY_SPEED);
// skip interval [-MIN_PLAY_SPEED MIN_PLAY_SPEED] // skip interval [-MIN_PLAY_SPEED MIN_PLAY_SPEED]
if (ABS(rate) < MIN_PLAY_SPEED) if (ABS(rate_) < MIN_PLAY_SPEED)
rate = SIGN(rate) * MIN_PLAY_SPEED; rate_ = SIGN(rate_) * MIN_PLAY_SPEED;
// apply with seek // apply with seek
execute_seek_command(); execute_seek_command();
} }
double MediaPlayer::PlaySpeed() const double MediaPlayer::playSpeed() const
{ {
return rate; return rate_;
} }
std::string MediaPlayer::Codec() const std::string MediaPlayer::codec() const
{ {
return codec_name; return codec_name_;
} }
double MediaPlayer::FrameRate() const double MediaPlayer::frameRate() const
{ {
return framerate; return framerate_;
} }
double MediaPlayer::UpdateFrameRate() const double MediaPlayer::updateFrameRate() const
{ {
return timecount.framerate(); return timecount_.frameRate();
} }
@@ -617,33 +617,33 @@ double MediaPlayer::UpdateFrameRate() const
bool MediaPlayer::fill_v_frame(GstBuffer *buf) bool MediaPlayer::fill_v_frame(GstBuffer *buf)
{ {
// always empty frame before filling it again // always empty frame before filling it again
if (v_frame.buffer) if (v_frame_.buffer)
gst_video_frame_unmap(&v_frame); gst_video_frame_unmap(&v_frame_);
// get the frame from buffer // get the frame from buffer
if ( !gst_video_frame_map (&v_frame, &v_frame_video_info, buf, GST_MAP_READ ) ) { if ( !gst_video_frame_map (&v_frame_, &v_frame_video_info_, buf, GST_MAP_READ ) ) {
Log::Info("MediaPlayer %s Failed to map the video buffer"); Log::Info("MediaPlayer %s Failed to map the video buffer");
return false; return false;
} }
// validate frame format // validate frame format
if( GST_VIDEO_INFO_IS_RGB(&(v_frame).info) && GST_VIDEO_INFO_N_PLANES(&(v_frame).info) == 1) { if( GST_VIDEO_INFO_IS_RGB(&(v_frame_).info) && GST_VIDEO_INFO_N_PLANES(&(v_frame_).info) == 1) {
// validate time // validate time
if (position != buf->pts) { if (position_ != buf->pts) {
// got a new RGB frame ! // got a new RGB frame !
v_frame_is_full = true; v_frame_is_full_ = true;
// get presentation time stamp // get presentation time stamp
position = buf->pts; position_ = buf->pts;
// set start position (i.e. pts of first frame we got) // set start position (i.e. pts of first frame we got)
if (start_position == GST_CLOCK_TIME_NONE) if (start_position_ == GST_CLOCK_TIME_NONE)
start_position = position; start_position_ = position_;
// keep update time (i.e. actual FPS of update) // keep update time (i.e. actual FPS of update)
timecount.tic(); timecount_.tic();
} }
} }
@@ -655,7 +655,7 @@ GstFlowReturn MediaPlayer::callback_pull_sample_video (GstElement *bin, MediaPla
{ {
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
if (m && !m->v_frame_is_full) { if (m && !m->v_frame_is_full_) {
// get last sample (non blocking) // get last sample (non blocking)
GstSample *sample = nullptr; GstSample *sample = nullptr;
@@ -692,7 +692,7 @@ void MediaPlayer::callback_end_of_video (GstElement *bin, MediaPlayer *m)
{ {
if (m) { if (m) {
// reached end of stream (eos) : might need to loop ! // reached end of stream (eos) : might need to loop !
m->need_loop = true; m->need_loop_ = true;
} }
} }
@@ -706,22 +706,22 @@ void MediaPlayer::callback_discoverer_process (GstDiscoverer *discoverer, GstDis
GstDiscovererResult result = gst_discoverer_info_get_result (info); GstDiscovererResult result = gst_discoverer_info_get_result (info);
switch (result) { switch (result) {
case GST_DISCOVERER_URI_INVALID: case GST_DISCOVERER_URI_INVALID:
m->discoverer_message << "Invalid URI: " << uri; m->discoverer_message_ << "Invalid URI: " << uri;
break; break;
case GST_DISCOVERER_ERROR: case GST_DISCOVERER_ERROR:
m->discoverer_message << "Error: " << err->message; m->discoverer_message_ << "Error: " << err->message;
break; break;
case GST_DISCOVERER_TIMEOUT: case GST_DISCOVERER_TIMEOUT:
m->discoverer_message << "Time out"; m->discoverer_message_ << "Time out";
break; break;
case GST_DISCOVERER_BUSY: case GST_DISCOVERER_BUSY:
m->discoverer_message << "Busy"; m->discoverer_message_ << "Busy";
break; break;
case GST_DISCOVERER_MISSING_PLUGINS: case GST_DISCOVERER_MISSING_PLUGINS:
{ {
const GstStructure *s = gst_discoverer_info_get_misc (info); const GstStructure *s = gst_discoverer_info_get_misc (info);
gchar *str = gst_structure_to_string (s); gchar *str = gst_structure_to_string (s);
m->discoverer_message << "Unknown file format / " << str; m->discoverer_message_ << "Unknown file format / " << str;
g_free (str); g_free (str);
} }
break; break;
@@ -741,26 +741,26 @@ void MediaPlayer::callback_discoverer_process (GstDiscoverer *discoverer, GstDis
{ {
// found a video / image stream : fill-in information // found a video / image stream : fill-in information
GstDiscovererVideoInfo* vinfo = GST_DISCOVERER_VIDEO_INFO(tmpinf); GstDiscovererVideoInfo* vinfo = GST_DISCOVERER_VIDEO_INFO(tmpinf);
m->width = gst_discoverer_video_info_get_width(vinfo); m->width_ = gst_discoverer_video_info_get_width(vinfo);
m->height = gst_discoverer_video_info_get_height(vinfo); m->height_ = gst_discoverer_video_info_get_height(vinfo);
m->isimage = gst_discoverer_video_info_is_image(vinfo); m->isimage_ = gst_discoverer_video_info_is_image(vinfo);
m->interlaced = gst_discoverer_video_info_is_interlaced(vinfo); m->interlaced_ = gst_discoverer_video_info_is_interlaced(vinfo);
guint parn = gst_discoverer_video_info_get_par_num(vinfo); guint parn = gst_discoverer_video_info_get_par_num(vinfo);
guint pard = gst_discoverer_video_info_get_par_denom(vinfo); guint pard = gst_discoverer_video_info_get_par_denom(vinfo);
m->par_width = (m->width * parn) / pard; m->par_width_ = (m->width_ * parn) / pard;
// if its a video, it duration, framerate, etc. // if its a video, it duration, framerate, etc.
if ( !m->isimage ) { if ( !m->isimage_ ) {
m->duration = gst_discoverer_info_get_duration (info); m->duration_ = gst_discoverer_info_get_duration (info);
m->seekable = gst_discoverer_info_get_seekable (info); m->seekable_ = gst_discoverer_info_get_seekable (info);
guint frn = gst_discoverer_video_info_get_framerate_num(vinfo); guint frn = gst_discoverer_video_info_get_framerate_num(vinfo);
guint frd = gst_discoverer_video_info_get_framerate_denom(vinfo); guint frd = gst_discoverer_video_info_get_framerate_denom(vinfo);
m->framerate = static_cast<double>(frn) / static_cast<double>(frd); m->framerate_ = static_cast<double>(frn) / static_cast<double>(frd);
m->frame_duration = (GST_SECOND * static_cast<guint64>(frd)) / (static_cast<guint64>(frn)); m->frame_duration_ = (GST_SECOND * static_cast<guint64>(frd)) / (static_cast<guint64>(frn));
} }
// try to fill-in the codec information // try to fill-in the codec information
GstCaps *caps = gst_discoverer_stream_info_get_caps (tmpinf); GstCaps *caps = gst_discoverer_stream_info_get_caps (tmpinf);
if (caps) { if (caps) {
m->codec_name = std::string( gst_pb_utils_get_codec_description(caps) ); m->codec_name_ = std::string( gst_pb_utils_get_codec_description(caps) );
gst_caps_unref (caps); gst_caps_unref (caps);
} }
// const GstTagList *tags = gst_discoverer_stream_info_get_tags(tmpinf); // const GstTagList *tags = gst_discoverer_stream_info_get_tags(tmpinf);
@@ -780,7 +780,7 @@ void MediaPlayer::callback_discoverer_process (GstDiscoverer *discoverer, GstDis
gst_discoverer_stream_info_list_free(streams); gst_discoverer_stream_info_list_free(streams);
if (!foundvideostream) { if (!foundvideostream) {
m->discoverer_message << "No video stream."; m->discoverer_message_ << "No video stream.";
} }
} }
@@ -791,11 +791,11 @@ void MediaPlayer::callback_discoverer_finished(GstDiscoverer *discoverer, MediaP
// finished the discoverer : finalize open status // finished the discoverer : finalize open status
if (m) { if (m) {
// no error message, open media // no error message, open media
if ( m->discoverer_message.str().empty()) if ( m->discoverer_message_.str().empty())
m->execute_open(); m->execute_open();
else { else {
Log::Warning("MediaPlayer %s Failed to open %s\n%s", m->id.c_str(), m->uri.c_str(), m->discoverer_message.str().c_str()); Log::Warning("MediaPlayer %s Failed to open %s\n%s", m->id_.c_str(), m->uri_.c_str(), m->discoverer_message_.str().c_str());
m->discoverer_message.clear(); m->discoverer_message_.clear();
} }
} }
} }
@@ -837,7 +837,7 @@ void TimeCounter::reset ()
fps = 0.f; fps = 0.f;
} }
float TimeCounter::framerate() const float TimeCounter::frameRate() const
{ {
return fps; return fps;
} }

View File

@@ -28,7 +28,7 @@ public:
TimeCounter(); TimeCounter();
void tic(); void tic();
void reset(); void reset();
float framerate() const; float frameRate() const;
}; };
struct MediaSegment struct MediaSegment
@@ -101,7 +101,7 @@ public:
/** /**
* Open a media using gstreamer URI * Open a media using gstreamer URI
* */ * */
void Open( std::string uri); void open( std::string uri_);
/** /**
* True if a media was oppenned * True if a media was oppenned
* */ * */
@@ -109,17 +109,17 @@ public:
/** /**
* Close the Media * Close the Media
* */ * */
void Close(); void close();
/** /**
* Update status * Update status
* Must be called in update loop * Must be called in update loop
* */ * */
void Update(); void update();
/** /**
* Pause / Play * Pause / Play
* Can play backward if play speed is negative * Can play backward if play speed is negative
* */ * */
void Play(bool on); void play(bool on);
/** /**
* Get Pause / Play * Get Pause / Play
* */ * */
@@ -128,12 +128,12 @@ public:
* Speed factor for playing * Speed factor for playing
* Can be negative. * Can be negative.
* */ * */
double PlaySpeed() const; double playSpeed() const;
/** /**
* Set the speed factor for playing * Set the speed factor for playing
* Can be negative. * Can be negative.
* */ * */
void SetPlaySpeed(double s); void setPlaySpeed(double s);
/** /**
* True if the player will loop when at begin or end * True if the player will loop when at begin or end
* */ * */
@@ -142,7 +142,7 @@ public:
LOOP_REWIND = 1, LOOP_REWIND = 1,
LOOP_BIDIRECTIONAL = 2 LOOP_BIDIRECTIONAL = 2
} LoopMode; } LoopMode;
LoopMode Loop() const; LoopMode loop() const;
/** /**
* Set the player to loop * Set the player to loop
* */ * */
@@ -150,58 +150,58 @@ public:
/** /**
* Restart from zero * Restart from zero
* */ * */
void Rewind(); void rewind();
/** /**
* Seek to next frame when paused * Seek to next frame when paused
* Can go backward if play speed is negative * Can go backward if play speed is negative
* */ * */
void SeekNextFrame(); void seekNextFrame();
/** /**
* Seek to any position in media * Seek to any position in media
* pos in nanoseconds. * pos in nanoseconds.
* */ * */
void SeekTo(GstClockTime pos); void seekTo(GstClockTime pos);
/** /**
* Jump by 10% of the duration * Jump by 10% of the duration
* */ * */
void FastForward(); void fastForward();
/** /**
* Get position time * Get position time
* */ * */
GstClockTime Position(); GstClockTime position();
/** /**
* Get total duration time * Get total duration time
* */ * */
GstClockTime Duration(); GstClockTime duration();
/** /**
* Get duration of one frame * Get duration of one frame
* */ * */
GstClockTime FrameDuration(); GstClockTime frameDuration();
/** /**
* Get framerate of the media * Get framerate of the media
* */ * */
double FrameRate() const; double frameRate() const;
/** /**
* Get name of Codec of the media * Get name of Codec of the media
* */ * */
std::string Codec() const; std::string codec() const;
/** /**
* Get rendering update framerate * Get rendering update framerate
* measured during play * measured during play
* */ * */
double UpdateFrameRate() const; double updateFrameRate() const;
/** /**
* Bind / Get the OpenGL texture * Bind / Get the OpenGL texture
* Must be called in OpenGL context * Must be called in OpenGL context
* */ * */
void Bind(); void bind();
guint Texture() const; guint texture() const;
/** /**
* Get Image properties * Get Image properties
* */ * */
guint Width() const; guint width() const;
guint Height() const; guint height() const;
float AspectRatio() const; float aspectRatio() const;
/** /**
* Accept visitors * Accept visitors
@@ -216,37 +216,37 @@ private:
bool removeAllPlaySegmentOverlap(MediaSegment s); bool removeAllPlaySegmentOverlap(MediaSegment s);
std::list< std::pair<guint64, guint64> > getPlaySegments() const; std::list< std::pair<guint64, guint64> > getPlaySegments() const;
std::string id; std::string id_;
std::string uri; std::string uri_;
guint textureindex; guint textureindex_;
guint width; guint width_;
guint height; guint height_;
guint par_width; // width to match pixel aspect ratio guint par_width_; // width to match pixel aspect ratio
GstClockTime position; GstClockTime position_;
GstClockTime start_position; GstClockTime start_position_;
GstClockTime duration; GstClockTime duration_;
GstClockTime frame_duration; GstClockTime frame_duration_;
gdouble rate; gdouble rate_;
LoopMode loop; LoopMode loop_;
TimeCounter timecount; TimeCounter timecount_;
gdouble framerate; gdouble framerate_;
GstState desired_state; GstState desired_state_;
GstElement *pipeline; GstElement *pipeline_;
GstDiscoverer *discoverer; GstDiscoverer *discoverer_;
std::stringstream discoverer_message; std::stringstream discoverer_message_;
std::string codec_name; std::string codec_name_;
GstVideoFrame v_frame; GstVideoFrame v_frame_;
GstVideoInfo v_frame_video_info; GstVideoInfo v_frame_video_info_;
std::atomic<bool> v_frame_is_full; std::atomic<bool> v_frame_is_full_;
std::atomic<bool> need_loop; std::atomic<bool> need_loop_;
MediaSegmentSet segments; MediaSegmentSet segments_;
MediaSegmentSet::iterator current_segment; MediaSegmentSet::iterator current_segment_;
bool ready; bool ready_;
bool seekable; bool seekable_;
bool isimage; bool isimage_;
bool interlaced; bool interlaced_;
void execute_open(); void execute_open();
void execute_loop_command(); void execute_loop_command();
@@ -255,8 +255,8 @@ private:
static GstFlowReturn callback_pull_sample_video (GstElement *bin, MediaPlayer *m); static GstFlowReturn callback_pull_sample_video (GstElement *bin, MediaPlayer *m);
static void callback_end_of_video (GstElement *bin, MediaPlayer *m); static void callback_end_of_video (GstElement *bin, MediaPlayer *m);
static void callback_discoverer_process (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, MediaPlayer *m); static void callback_discoverer_process (GstDiscoverer *discoverer_, GstDiscovererInfo *info, GError *err, MediaPlayer *m);
static void callback_discoverer_finished(GstDiscoverer *discoverer, MediaPlayer *m); static void callback_discoverer_finished(GstDiscoverer *discoverer_, MediaPlayer *m);
}; };