Support DRM playback 03/318703/4 accepted/tizen_unified_toolchain accepted/tizen/unified/20241017.114640 accepted/tizen/unified/toolchain/20241022.122553 accepted/tizen/unified/toolchain/20241022.123009 accepted/tizen/unified/x/20241017.170357 accepted/tizen/unified/x/asan/20241022.113522
authorHaesu Gwon <haesu.gwon@samsung.com>
Mon, 7 Oct 2024 07:37:32 +0000 (16:37 +0900)
committerHaesu Gwon <haesu.gwon@samsung.com>
Tue, 8 Oct 2024 05:10:58 +0000 (14:10 +0900)
- Change video and audio pipeline for DRM playback

[Version] 0.1.3
[Issue Type] Add feature

Change-Id: I1c76006dad9f6cd81306ec4d434c08eed6c50123

packaging/libtrackrenderer.spec
src/gstcaps_builder.cpp
src/trackrenderer.cpp

index 690553010ef810ac5586144a4f1af55c384648d8..5f41d77935e700a81d9e76f8b6720452d7a4faed 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libtrackrenderer
 Summary:    new multimedia streaming player trackrenderer
-Version:    0.1.2
+Version:    0.1.3
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 41b298429607ef0f2eb40da8b2756a1d1f158004..9b89121266fef6bbbe89fd9c5c8bd99e9f78d7ea 100644 (file)
@@ -75,9 +75,10 @@ static void FillStreamFormat(const GstCapsWrapper& caps, const Track& track) {
   caps.SetValue("adaptive-streaming", G_TYPE_BOOLEAN, true);
 }
 
-static void FillDrmInfo(const GstCapsWrapper& caps, const Track& track) {
-  if (!track.original_media_type.empty())
-    caps.SetValue("original-media-type", G_TYPE_STRING, track.original_media_type.c_str());
+static void FillDrmInfo(const GstCapsWrapper& caps, const Track& track, const std::string& originalMediaType) {
+  if (!originalMediaType.empty())
+    caps.SetValue("original-media-type", G_TYPE_STRING, originalMediaType.c_str());
+
 
   if (!track.protection_system.empty())
     caps.SetValue("protection-system", G_TYPE_STRING, track.protection_system.c_str());
@@ -259,7 +260,7 @@ GstCapsWrapper GstCapsBuilder::Build(const Track& track, bool is_drm) {
   internal::FillStreamType(caps, track);
   internal::FillCodecData(caps, track);
   internal::FillStreamFormat(caps, track);
-  internal::FillDrmInfo(caps, track);
+  internal::FillDrmInfo(caps, track, is_drm ? media_type : std::string());
   internal::FillChannelMaskField(caps, track);
 
   caps.PrintCapsString();
index 7f301d46698f8463bf478461d9763208e6530781..69d6efc13af1f054e7e3c73999cf0cd7cf14cbc2 100644 (file)
@@ -1061,21 +1061,16 @@ static GstCaps* ChooseDecoderCaps(GstCaps* inputCaps, GstCaps* parseCaps)
 bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
   TRACKRENDERER_ENTER;
 
-  auto caps = caps_builder_.Build(*track, internal::IsDrmEmeElementNecessary(
-                                          drm_property_, track->mimetype));
-  CreateAppSrc_(kTrackTypeVideo, caps.GetCaps_());
-
-  if (internal::IsDecryptorElementNecessary(drm_property_)) {
-    auto caps_for_parser = caps_builder_.BuildOrgMediaType(*track, internal::IsDrmEmeElementNecessary(
-                                          drm_property_, track->mimetype));
-    if (!pipeline_->FactoryMake(Elements::kParseVideo, caps_for_parser.GetCaps_(),
+  bool is_drm = internal::IsDrmEmeElementNecessary(drm_property_, track->mimetype);
+
+  auto caps = caps_builder_.Build(*track, false);
+
+  LOGD("track->mimetype[%s]", track->mimetype.c_str());
+  CreateAppSrc_(kTrackTypeVideo, is_drm ? caps_builder_.Build(*track, true).GetCaps_() : caps.GetCaps_());
+
+  if (!pipeline_->FactoryMake(Elements::kParseVideo, caps.GetCaps_(),
                           GST_ELEMENT_FACTORY_TYPE_PARSER, NULL))
-      TRACKRENDERER_ERROR("Failed to make parser");
-  } else {
-    if (!pipeline_->FactoryMake(Elements::kParseVideo, caps.GetCaps_(),
-                            GST_ELEMENT_FACTORY_TYPE_PARSER, NULL))
-      TRACKRENDERER_ERROR("Failed to make parser");
-  }
+    TRACKRENDERER_ERROR("Failed to make parser");
 
   auto parse_caps =
       gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseVideo));
@@ -1102,15 +1097,7 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
   pipeline_->SignalConnect(Elements::kCCExtractor, "pad-added",
                              G_CALLBACK(GstClosedCaptionPadAddedCb_), this);
 
-  // TODO: need to implement drmdecryptor plugin
-  // FIXME: drm plugin should be added before parser
-  if (internal::IsDecryptorElementNecessary(drm_property_)) {
-    pipeline_->FactoryMake(Elements::kDrmVideo, "cencdecrypt", NULL);
-    pipeline_->SetProperty(Elements::kDrmVideo, "getrights-complete-cb",
-                GstVideoDrmInitDataCb_);
-    pipeline_->SetProperty(Elements::kDrmVideo, "getrights-complete-cb-data",
-                this);
-  } else if (internal::IsDrmEmeElementNecessary(drm_property_, track->mimetype)) {
+  if (is_drm) {
     pipeline_->FactoryMake(Elements::kDrmVideo, "drm_eme", "video_drm");
     pipeline_->SetProperty(Elements::kDrmVideo, "plus-player-eme", TRUE);
     if (!internal::IsExternalDecryptionCase(drm_property_)) {
@@ -1160,11 +1147,18 @@ void TrackRenderer::SetOpusChannelMappingFamily(const GstCapsWrapper& caps) {
 bool TrackRenderer::CreateAudioPipeline_(const Track* track) {
   TRACKRENDERER_ENTER;
 
+  bool is_drm = internal::IsDrmEmeElementNecessary(drm_property_, track->mimetype);
+
   auto caps = caps_builder_.Build(*track, false);
-  if (track->mimetype.find("audio/x-opus") != std::string::npos)
+  auto drm_caps = caps_builder_.Build(*track, true);
+  if (track->mimetype.find("audio/x-opus") != std::string::npos) {
     SetOpusChannelMappingFamily(caps);
 
-  CreateAppSrc_(kTrackTypeAudio, caps.GetCaps_());
+    if (is_drm)
+      SetOpusChannelMappingFamily(drm_caps);
+  }
+
+  CreateAppSrc_(kTrackTypeAudio, is_drm ? drm_caps.GetCaps_() : caps.GetCaps_());
 
   if (!pipeline_->FactoryMake(Elements::kParseAudio, caps.GetCaps_(),
                           GST_ELEMENT_FACTORY_TYPE_PARSER, NULL))
@@ -1190,7 +1184,18 @@ bool TrackRenderer::CreateAudioPipeline_(const Track* track) {
   pipeline_->FactoryMake(Elements::kAudioConvert, "audioconvert", nullptr);
   pipeline_->FactoryMake(Elements::kAudioResample, "audioresample", nullptr);
 
-  pipeline_->BinAdd(Elements::kBinAudio, Elements::kAppSrcAudio,
+  if (is_drm) {
+    pipeline_->FactoryMake(Elements::kDrmAudio, "drm_eme", "audio_drm");
+    pipeline_->SetProperty(Elements::kDrmAudio, "plus-player-eme", TRUE);
+    if (!internal::IsExternalDecryptionCase(drm_property_)) {
+      pipeline_->SetProperty(Elements::kDrmAudio, "getrights-complete-cb",
+                             GstAudioDrmInitDataCb_);
+      pipeline_->SetProperty(Elements::kDrmAudio, "getrights-complete-cb-data",
+                             this);
+    }
+  }
+
+  pipeline_->BinAdd(Elements::kBinAudio, Elements::kAppSrcAudio, Elements::kDrmAudio,
                     Elements::kParseAudio, Elements::kDecAudio,
                     Elements::kAudioConvert, Elements::kAudioResample,
                     Elements::kSinkAudio);
@@ -1914,6 +1919,17 @@ GstPadProbeReturn TrackRenderer::GstPadProbeAppsrcEventCb_(GstPad* pad,
     type = kTrackTypeVideo;
   } else if (strstr(name, "text")) {
     type = kTrackTypeSubtitle;
+  } else if (strstr(name, "drm/eme")) {
+    const gchar * original_media_type = gst_structure_get_string(str, "original-media-type");
+
+    if (strstr(original_media_type, "audio")) {
+      type = kTrackTypeAudio;
+    } else if (strstr(original_media_type, "video")) {
+      type = kTrackTypeVideo;
+    } else {
+      TRACKRENDERER_WARN("invalid name %s", name);
+      return GST_PAD_PROBE_PASS;
+    }
   } else {
     TRACKRENDERER_WARN("invalid name %s", name);
     return GST_PAD_PROBE_PASS;
@@ -2188,7 +2204,7 @@ bool TrackRenderer::Activate(TrackType type, const Track& track) {
       pipeline_->SetProperty(Elements::kDrmVideo, "getrights-complete-cb-data",
                   this);
     }
-    pipeline_->BinAdd(Elements::kBinVideo, Elements::kDrmVideo,
+    pipeline_->BinAdd(Elements::kBinVideo, Elements::kDrmVideo, Elements::kParseVideo,
                       Elements::kDecVideo, Elements::kSinkVideo);
     pipeline_->SetProperty(Elements::kSinkVideo, "async", TRUE);
     GstElementLowLatency_(kTrackTypeVideo);