Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/beta'
Browse files Browse the repository at this point in the history
  • Loading branch information
brunoherbelin committed May 18, 2024
2 parents 7b5bc6d + b38017e commit d87a84d
Show file tree
Hide file tree
Showing 17 changed files with 433 additions and 208 deletions.
77 changes: 65 additions & 12 deletions src/FrameGrabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ FrameGrabber::FrameGrabber(): finished_(false), initialized_(false), active_(fal
endofstream_(false), accept_buffer_(false), buffering_full_(false), pause_(false),
pipeline_(nullptr), src_(nullptr), caps_(nullptr), timer_(nullptr), timer_firstframe_(0),
timer_pauseframe_(0), timestamp_(0), duration_(0), pause_duration_(0), frame_count_(0),
buffering_size_(MIN_BUFFER_SIZE), buffering_count_(0), timestamp_on_clock_(true)
keyframe_count_(0), buffering_size_(MIN_BUFFER_SIZE), buffering_count_(0), timestamp_on_clock_(true)
{
// unique id
id_ = BaseToolkit::uniqueId();
Expand Down Expand Up @@ -319,11 +319,16 @@ void FrameGrabber::setPaused(bool pause)
{
// can pause only if already active
if (active_) {

// keep time of switch from not-paused to paused
if (pause && !pause_)
timer_pauseframe_ = gst_clock_get_time(timer_);

// set to paused
pause_ = pause;

// pause pipeline
gst_element_set_state (pipeline_, pause_ ? GST_STATE_PAUSED : GST_STATE_PLAYING);
}
}

Expand Down Expand Up @@ -369,11 +374,32 @@ void FrameGrabber::callback_enough_data (GstAppSrc *, gpointer p)
if (grabber) {
grabber->accept_buffer_ = false;
#ifndef NDEBUG
Log::Info("Frame capture : Buffer full");
Log::Info("Frame capture : Buffer full");
#endif
}
}


GstBusSyncReply FrameGrabber::signal_handler(GstBus *, GstMessage *msg, gpointer ptr)
{
// only handle error messages
if (ptr != nullptr && GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
// inform user
GError *error;
gst_message_parse_error(msg, &error, NULL);
Log::Warning("FrameGrabber %s : %s",
std::to_string(reinterpret_cast<FrameGrabber *>(ptr)->id()).c_str(),
error->message);
g_error_free(error);
// } else {
// g_printerr("FrameGrabber msg %s \n", GST_MESSAGE_TYPE_NAME(msg));
}

// drop all messages to avoid filling up the stack
return GST_BUS_DROP;
}


GstPadProbeReturn FrameGrabber::callback_event_probe(GstPad *, GstPadProbeInfo * info, gpointer p)
{
GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
Expand Down Expand Up @@ -409,6 +435,15 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)

// if initialization succeeded
if (initialized_) {

#ifdef IGNORE_GST_ERROR_MESSAGE
// avoid filling up bus with messages
gst_bus_set_flushing(gst_element_get_bus(pipeline_), true);
#else
// set message handler for the pipeline's bus
gst_bus_set_sync_handler(gst_element_get_bus(pipeline_),
FrameGrabber::signal_handler, this, NULL);
#endif
// attach EOS detector
GstPad *pad = gst_element_get_static_pad (gst_bin_get_by_name (GST_BIN (pipeline_), "sink"), "sink");
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, FrameGrabber::callback_event_probe, this, NULL);
Expand Down Expand Up @@ -458,6 +493,12 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
if (timer_pauseframe_ > 0) {
// compute duration of the pausing time and add to total pause duration
pause_duration_ += gst_clock_get_time(timer_) - timer_pauseframe_;

// sync audio packets
GstElement *audiosync = GST_ELEMENT_CAST(gst_bin_get_by_name(GST_BIN(pipeline_), "audiosync"));
if (audiosync)
g_object_set(G_OBJECT(audiosync), "ts-offset", -timer_pauseframe_, NULL);

// reset pause frame time
timer_pauseframe_ = 0;
}
Expand All @@ -469,25 +510,31 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
// if time is zero (first frame) or if delta time is passed one frame duration (with a margin)
if ( t == 0 || (t - duration_) > (frame_duration_ - 3000) ) {

// count frames
frame_count_++;

// set duration to an exact multiples of frame duration
duration_ = ( t / frame_duration_) * frame_duration_;
// add a key frame every second (if keyframecount is valid)
if (keyframe_count_ > 1 && frame_count_ % keyframe_count_ < 1) {
GstEvent *event
= gst_video_event_new_downstream_force_key_unit(timestamp_,
GST_CLOCK_TIME_NONE,
GST_CLOCK_TIME_NONE,
FALSE,
frame_count_ / keyframe_count_);
gst_element_send_event(GST_ELEMENT(src_), event);
}

if (timestamp_on_clock_)
// automatic frame presentation time stamp
// automatic frame presentation time stamp (DURATION PRIORITY)
// Pipeline set to "do-timestamp"=TRUE
// set timestamp to actual time
timestamp_ = duration_;
else {
// monotonic timestamp increment to keep fixed FPS
// force frame presentation timestamp (FRAMERATE PRIORITY)
// Pipeline set to "do-timestamp"=FALSE
timestamp_ += frame_duration_;
// force frame presentation timestamp
buffer->pts = timestamp_;
GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer) = timestamp_;
// set frame duration
buffer->duration = frame_duration_;
// monotonic timestamp increment to keep fixed FPS
// Pipeline set to "do-timestamp"=FALSE
timestamp_ += frame_duration_;
}

// when buffering is (almost) full, refuse buffer 1 frame over 2
Expand All @@ -513,6 +560,12 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
// push frame
gst_app_src_push_buffer (src_, buffer);
// NB: buffer will be unrefed by the appsrc

// count frames
frame_count_++;

// update duration to an exact multiples of frame duration
duration_ = ( t / frame_duration_) * frame_duration_;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/FrameGrabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class FrameGrabber
GstClockTime pause_duration_;
GstClockTime frame_duration_;
guint64 frame_count_;
guint64 keyframe_count_;
guint64 buffering_size_;
guint64 buffering_count_;
bool timestamp_on_clock_;
Expand All @@ -96,6 +97,7 @@ class FrameGrabber
static void callback_need_data (GstAppSrc *, guint, gpointer user_data);
static void callback_enough_data (GstAppSrc *, gpointer user_data);
static GstPadProbeReturn callback_event_probe(GstPad *, GstPadProbeInfo *info, gpointer user_data);
static GstBusSyncReply signal_handler(GstBus *, GstMessage *, gpointer);
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Loopback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ std::string Loopback::init(GstCaps *caps)

// specify streaming framerate in the given caps
GstCaps *tmp = gst_caps_copy( caps );
GValue v = { 0, };
GValue v = G_VALUE_INIT;
g_value_init (&v, GST_TYPE_FRACTION);
gst_value_set_fraction (&v, LOOPBACK_FPS, 1); // fixed FPS
gst_caps_set_value(tmp, "framerate", &v);
Expand Down
10 changes: 8 additions & 2 deletions src/MediaPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ GstBusSyncReply MediaPlayer::signal_handler(GstBus *, GstMessage *msg, gpointer
// inform user
GError *error;
gst_message_parse_error(msg, &error, NULL);
Log::Warning("MediaPlayer %s : %s - %s",
Log::Warning("MediaPlayer %s : %s",
std::to_string(reinterpret_cast<MediaPlayer*>(ptr)->id()).c_str(),
error->message);
g_error_free(error);
Expand Down Expand Up @@ -452,6 +452,9 @@ void MediaPlayer::execute_open()
GstAppSinkCallbacks callbacks;
#if GST_VERSION_MINOR > 18 && GST_VERSION_MAJOR > 0
callbacks.new_event = NULL;
#if GST_VERSION_MINOR > 23
callbacks.propose_allocation = NULL;
#endif
#endif
callbacks.new_preroll = callback_new_preroll;
if (singleFrame()) {
Expand Down Expand Up @@ -494,7 +497,7 @@ void MediaPlayer::execute_open()

#ifdef IGNORE_GST_ERROR_MESSAGE
// avoid filling up bus with messages
gst_bus_set_flushing(bus, true);
gst_bus_set_flushing(gst_element_get_bus(pipeline_), true);
#else
// set message handler for the pipeline's bus
gst_bus_set_sync_handler(gst_element_get_bus(pipeline_),
Expand Down Expand Up @@ -639,6 +642,9 @@ void MediaPlayer::execute_open()
GstAppSinkCallbacks callbacks;
#if GST_VERSION_MINOR > 18 && GST_VERSION_MAJOR > 0
callbacks.new_event = NULL;
#if GST_VERSION_MINOR > 23
callbacks.propose_allocation = NULL;
#endif
#endif
callbacks.new_preroll = callback_new_preroll;
if (singleFrame()) {
Expand Down
Loading

0 comments on commit d87a84d

Please sign in to comment.