#include "trackrenderer/core/gst_utils.h"
#include "trackrenderer/core/gstobject_guard.h"
+#include "trackrenderer/core/low_latency_mode.h"
#include "trackrenderer/core/track_util.h"
#include "trackrenderer/core/utils/log.h"
#include "trackrenderer/display.h"
}
inline bool IsLowLatencyModeDisableAVSync(std::uint32_t low_latency_mode) {
- constexpr std::uint32_t kAVSync = 0x0100;
+ constexpr std::uint32_t kAVSync = static_cast<std::uint32_t>(kLowLatencyModeDisableAVSync);
return (low_latency_mode & kAVSync) ? true : false;
}
+inline bool IsLowLatencyModeDisablePreroll(std::uint32_t low_latency_mode) {
+ constexpr std::uint32_t kPreroll = static_cast<std::uint32_t>(kLowLatencyModeDisablePreroll);
+ return (low_latency_mode & kPreroll) ? true : false;
+}
+
int GetVideoWidth(const GstCaps* caps) {
GstStructure* structure = gst_caps_get_structure(caps, 0);
if (!structure) return 0;
return false;
}
+ if (!HasSubtitleOnly_() &&
+ !internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) &&
+ !internal::IsLowLatencyModeDisablePreroll(low_latency_mode_))
resource_cv_.wait(lock);
if (state_ != State::kWorking) {
return true;
}
+ if (type >= kTrackTypeMax) return false;
if (trackctx_[type].index == kInvalidTrackIndex // Track is not activated.
|| data->GetIndex() != trackctx_[type].index) {
TRACKRENDERER_DEBUG("ControlDropRate [%d] %d vs %d", type, data->GetIndex(), trackctx_[type].index);
auto parse_caps =
gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseVideo));
+ /* create video decoder */
GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
if (!track->use_swdecoder &&
!internal::GetIniValue(properties_, "use_default_video_codec_sw"))
return false;
}
+ /* create video sink */
DisplayType display_type;
display_->GetDisplay(&display_type);
const char* videosink_name = "fakesink";
return false;
}
- if (videosink_name &&
- (strstr(videosink_name, "fakesink") || strstr(videosink_name, kVideoSinkName))) {
- pipeline_->SignalConnect(Elements::kSinkVideo, "preroll-handoff",
- G_CALLBACK(GstPrerollDecodedVideoBufferCb_), this);
- pipeline_->SignalConnect(Elements::kSinkVideo, "handoff",
- G_CALLBACK(GstDecodedVideoBufferCb_), this);
- }
-
+ pipeline_->SignalConnect(Elements::kSinkVideo, "preroll-handoff",
+ G_CALLBACK(GstPrerollDecodedVideoBufferCb_), this);
+ pipeline_->SignalConnect(Elements::kSinkVideo, "handoff",
+ G_CALLBACK(GstDecodedVideoBufferCb_), this);
pipeline_->SignalConnect(Elements::kSinkVideo, "sink", "notify::caps",
G_CALLBACK(GstCapsNotifyCb_), this);
this);
}
}
-
+ /* setup remained video path according to video dec type */
if (pipeline_->IsFactoryListType(Elements::kDecVideo, GST_ELEMENT_FACTORY_TYPE_HARDWARE)) {
TRACKRENDERER_INFO("HW codec");
- if (videosink_name && strstr(videosink_name, kVideoSinkName))
+ if (strstr(videosink_name, kVideoSinkName))
pipeline_->SetProperty(Elements::kSinkVideo, "use-tbm", true);
} else {
TRACKRENDERER_INFO("SW codec");
pipeline_->FactoryMake(Elements::kVideoConvert, "videoconvert", NULL);
pipeline_->SetProperty(Elements::kVideoConvert, "n-threads", 2);
- if (videosink_name && strstr(videosink_name, kVideoSinkName))
+ if (strstr(videosink_name, kVideoSinkName))
pipeline_->SetProperty(Elements::kSinkVideo, "use-tbm", false);
}
+ GstElementLowLatency_(kTrackTypeVideo);
pipeline_->BinAdd(Elements::kBinVideo, Elements::kAppSrcVideo, Elements::kDrmVideo,
Elements::kParseVideo, Elements::kDecVideo, Elements::kCCExtractor, Elements::kVideoQueue,
pipeline_->FactoryMake(Elements::kSinkAudio, kAudioSinkName, NULL);
pipeline_->SetProperty(Elements::kSinkAudio, "provide-clock", FALSE);
+ GstElementLowLatency_(kTrackTypeAudio);
pipeline_->CreateBin(Elements::kBinAudio, "audiobin");
pipeline_->SignalConnect(Elements::kAppSrcAudio, "need-data",
}
pipeline_->SetProperty(Elements::kSinkSubtitle, "sync", TRUE, "async", FALSE,
"signal-handoffs", TRUE);
+ GstElementLowLatency_(kTrackTypeSubtitle);
pipeline_->SignalConnect(Elements::kSinkSubtitle, "handoff",
G_CALLBACK(GstSubtitleDataHandOffCb_), this);
TRACKRENDERER_LEAVE;
trackrenderer->pipeline_->SetProperty(Elements::kSinkCaption, "sync", TRUE,
"async", FALSE, "signal-handoffs",
TRUE);
+ trackrenderer->GstElementLowLatency_(kTrackTypeSubtitle);
trackrenderer->pipeline_->SignalConnect(
Elements::kSinkCaption, "handoff", G_CALLBACK(GstClosedCaptionHandOffCb_),
userdata);
GST_APP_STREAM_TYPE_SEEKABLE);
pipeline_->SetProperty(Elements::kAppSrcAudio, "format", GST_FORMAT_TIME);
+ GstElementLowLatency_(kTrackTypeAudio);
pipeline_->BinAdd(Elements::kBinAudio,
Elements::kParseAudio, Elements::kDecAudio,
Elements::kAudioConvert, Elements::kAudioResample,
if (state_ == State::kStopped) return false;
if (!pipeline_) return false;
- Track active_track;
- if (!trackctx_[type].track ||
- track_util::GetActiveTrack(trackinfo_, type, &active_track)) {
- // Fix:: for external subtitle case, it may possible subtitle tracksource
- // prepared after main tracksource should be allowed to set subtitle current
- // track information in renderer trackctx_ so that it can be submitted to
- // subtitle renderer pipeline.
+ if (!trackctx_[type].track) {
if (type == kTrackTypeSubtitle) {
- TRACKRENDERER_ERROR("set subtitle track information in track renderer");
+ TRACKRENDERER_ERROR("set subtitle track information");
trackctx_[type].index = track.index;
trackinfo_.push_back(track);
return true;
}
- TRACKRENDERER_ERROR("Only valid but deactivated track can be activated.");
+
+ TRACKRENDERER_ERROR("invalid track");
+ return false;
+ }
+
+ Track active_track;
+ if (track_util::GetActiveTrack(trackinfo_, type, &active_track)) {
+ TRACKRENDERER_ERROR_P(this, "track type %d is already activated", type);
return false;
}
Elements::kDecVideo, Elements::kSinkVideo);
pipeline_->SetProperty(Elements::kSinkVideo, "sync", TRUE, "async", TRUE);
+ GstElementLowLatency_(kTrackTypeVideo);
+
pipeline_->SetAppSrcCaps(Elements::kAppSrcVideo, caps);
pipeline_->PadRemoveProbe(kPadProbeVideoBlock);
pipeline_->Execute(Elements::kSinkVideo, [this](GstElement* obj) noexcept {
void TrackRenderer::CreateTbmBufferManager_(const Track* track) {
TRACKRENDERER_ENTER;
- tbm_buffer_manager_.reset(new TbmBufferManager);
+ if (tbm_buffer_manager_ == nullptr)
+ tbm_buffer_manager_.reset(new TbmBufferManager);
}
bool TrackRenderer::GetVolume(int* volume) {
std::uint32_t val = boost::any_cast<std::uint32_t>(value);
TRACKRENDERER_ERROR(" Mode [%d]", val);
low_latency_mode_ = val;
+ if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+ unlimited_max_buffer_mode_ = true;
return true;
}
}
void TrackRenderer::GstElementLowLatency_(const TrackType& type) {
- if (low_latency_mode_ == 0) return;
+ if (low_latency_mode_ ==
+ static_cast<std::uint32_t>(LowLatencyMode::kLowLatencyModeNone))
+ return;
+
switch (type) {
case kTrackTypeAudio:
- if (low_latency_mode_ & kLowLatencyModeDisablePreroll) {
+ if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+ pipeline_->SetProperty(Elements::kSinkAudio, "sync", FALSE, "async", FALSE);
+ if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
pipeline_->SetProperty(Elements::kSinkAudio, "async", FALSE);
- }
break;
case kTrackTypeVideo:
- if (low_latency_mode_ & kLowLatencyModeDisablePreroll) {
+ if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+ pipeline_->SetProperty(Elements::kSinkVideo, "sync", FALSE, "async", FALSE);
+ if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
pipeline_->SetProperty(Elements::kSinkVideo, "async", FALSE);
- }
break;
case kTrackTypeSubtitle:
+ if (low_latency_mode_ & kLowLatencyModeDisableAVSync) {
+ pipeline_->SetProperty(Elements::kSinkCaption, "sync", FALSE, "async", FALSE);
+ pipeline_->SetProperty(Elements::kSinkSubtitle, "sync", FALSE, "async", FALSE);
+ }
+ if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
+ pipeline_->SetProperty(Elements::kSinkSubtitle, "async", FALSE);
break;
default:
TRACKRENDERER_ERROR("wrong track type");
pipeline_->BinAdd(Elements::kBinAudio, Elements::kDecAudio,
Elements::kSinkAudio);
pipeline_->SetProperty(Elements::kSinkAudio, "sync", TRUE, "async", TRUE);
- pipeline_->SetProperty(Elements::kSinkAudio, "multiview-window-id",
- static_cast<int>(display_->GetSurfaceId()));
+ GstElementLowLatency_(kTrackTypeAudio);
+
pipeline_->PadRemoveProbe(kPadProbeAudioBlock);
is_audioactivated_ = true;