• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "player_codec_ctrl.h"
17 #include "surface.h"
18 #include "media_log.h"
19 #include "media_errors.h"
20 
21 namespace {
22     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerCodecCtrl"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 constexpr uint32_t MAX_SOFT_BUFFERS = 10;
28 constexpr uint32_t DEFAULT_CACHE_BUFFERS = 1;
29 
PlayerCodecCtrl()30 PlayerCodecCtrl::PlayerCodecCtrl()
31 {
32     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
33 }
34 
~PlayerCodecCtrl()35 PlayerCodecCtrl::~PlayerCodecCtrl()
36 {
37     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
38     notifier_ = nullptr;
39     if (decoder_ != nullptr) {
40         if (signalId_ != 0) {
41             g_signal_handler_disconnect(decoder_, signalId_);
42             signalId_ = 0;
43         }
44         gst_object_unref(decoder_);
45         decoder_ = nullptr;
46     }
47 }
48 
SetupCodecCb(const std::string & metaStr,GstElement * src,GstElement * videoSink)49 void PlayerCodecCtrl::SetupCodecCb(const std::string &metaStr, GstElement *src, GstElement *videoSink)
50 {
51     if (metaStr.find("Codec/Decoder/Video/Hardware") != std::string::npos) {
52         // hardware dec
53         isHardwareDec_ = true;
54         if (decoder_ != nullptr) {
55             gst_object_unref(decoder_);
56             decoder_ = nullptr;
57         }
58         g_object_set(G_OBJECT(src), "player-mode", TRUE, nullptr);
59         decoder_ = GST_ELEMENT_CAST(gst_object_ref(src));
60         if (!codecTypeList_.empty()) {
61             // For hls scene when change codec, the second codec should not go performance mode process.
62             codecTypeList_.push_back(true);
63             return;
64         }
65         // For performance mode.
66         codecTypeList_.push_back(true);
67 
68         g_object_set(G_OBJECT(src), "enable-slice-cat", TRUE, nullptr); // Enable slice
69         g_object_set(G_OBJECT(src), "performance-mode", TRUE, nullptr);
70         g_object_set(G_OBJECT(videoSink), "performance-mode", TRUE, nullptr);
71 
72         GstCaps *caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", nullptr);
73         g_object_set(G_OBJECT(videoSink), "caps", caps, nullptr);
74         g_object_set(G_OBJECT(src), "sink-caps", caps, nullptr);
75         gst_caps_unref(caps);
76 
77         GstBufferPool *pool;
78         g_object_get(videoSink, "surface-pool", &pool, nullptr);
79         g_object_set(G_OBJECT(src), "surface-pool", pool, nullptr);
80     } else if (metaStr.find("Codec/Decoder/Video") != std::string::npos) {
81         // software dec
82         codecTypeList_.push_back(false);
83         isHardwareDec_ = false;
84     }
85 }
86 
DetectCodecSetup(const std::string & metaStr,GstElement * src,GstElement * videoSink)87 void PlayerCodecCtrl::DetectCodecSetup(const std::string &metaStr, GstElement *src, GstElement *videoSink)
88 {
89     std::lock_guard<std::mutex> lock(mutex_);
90     MEDIA_LOGD("Codec Setup");
91     SetupCodecCb(metaStr, src, videoSink);
92     SetupCodecBufferNum(metaStr, src);
93 }
94 
SetupCodecBufferNum(const std::string & metaStr,GstElement * src) const95 void PlayerCodecCtrl::SetupCodecBufferNum(const std::string &metaStr, GstElement *src) const
96 {
97     if (metaStr.find("Sink/Video") != std::string::npos && !isHardwareDec_) {
98         g_object_set(G_OBJECT(src), "max-pool-capacity", MAX_SOFT_BUFFERS, nullptr);
99         g_object_set(G_OBJECT(src), "cache-buffers-num", DEFAULT_CACHE_BUFFERS, nullptr);
100     }
101 }
102 
SetCapsFixErrorCb(CapsFixErrorNotifier notifier)103 void PlayerCodecCtrl::SetCapsFixErrorCb(CapsFixErrorNotifier notifier)
104 {
105     notifier_ = notifier;
106     CHECK_AND_RETURN_LOG(decoder_ != nullptr, "decoder_ is nullptr");
107     signalId_ = g_signal_connect(decoder_, "caps-fix-error", G_CALLBACK(&PlayerCodecCtrl::CapsFixErrorCb), this);
108 }
109 
CapsFixErrorCb(const GstElement * decoder,gpointer userData)110 void PlayerCodecCtrl::CapsFixErrorCb(const GstElement *decoder, gpointer userData)
111 {
112     MEDIA_LOGD("CapsFixErrorCb in");
113     if (decoder == nullptr || userData == nullptr) {
114         MEDIA_LOGE("param is nullptr");
115         return;
116     }
117 
118     auto playerCodecCtrl = static_cast<PlayerCodecCtrl *>(userData);
119     if (playerCodecCtrl->notifier_ != nullptr) {
120         playerCodecCtrl->notifier_();
121     }
122 }
123 
DetectCodecUnSetup(GstElement * src,GstElement * videoSink)124 void PlayerCodecCtrl::DetectCodecUnSetup(GstElement *src, GstElement *videoSink)
125 {
126     std::lock_guard<std::mutex> lock(mutex_);
127     (void)src;
128     MEDIA_LOGD("Codec UnSetup");
129     if (decoder_ != nullptr) {
130         gst_object_unref(decoder_);
131         decoder_ = nullptr;
132     }
133     HlsSwichSoftAndHardCodec(videoSink);
134 }
135 
HlsSwichSoftAndHardCodec(GstElement * videoSink)136 void PlayerCodecCtrl::HlsSwichSoftAndHardCodec(GstElement *videoSink)
137 {
138     if (codecTypeList_.empty()) {
139         MEDIA_LOGE("codec type list is empty");
140         return;
141     }
142 
143     bool codecType = codecTypeList_.front();
144     codecTypeList_.pop_front();
145     if ((codecTypeList_.empty()) || (codecType == codecTypeList_.front())) {
146         MEDIA_LOGD("codec type is empty or the next is same");
147         return;
148     }
149 
150     GstCaps *caps = nullptr;
151     if (codecTypeList_.front()) {
152         caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", nullptr);
153         g_object_set(G_OBJECT(videoSink), "max-pool-capacity", SURFACE_MAX_QUEUE_SIZE, nullptr);
154         g_object_set(G_OBJECT(videoSink), "cache-buffers-num", 0, nullptr);
155     } else {
156         caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "RGBA", nullptr);
157         g_object_set(G_OBJECT(videoSink), "max-pool-capacity", MAX_SOFT_BUFFERS, nullptr);
158         g_object_set(G_OBJECT(videoSink), "cache-buffers-num", DEFAULT_CACHE_BUFFERS, nullptr);
159     }
160     g_object_set(G_OBJECT(videoSink), "caps", caps, nullptr);
161     gst_caps_unref(caps);
162 }
163 
EnhanceSeekPerformance(bool enable)164 void PlayerCodecCtrl::EnhanceSeekPerformance(bool enable)
165 {
166     std::lock_guard<std::mutex> lock(mutex_);
167     if (isHardwareDec_ && decoder_ != nullptr) {
168         g_object_set(decoder_, "seeking", enable, nullptr);
169     }
170 }
171 } // Media
172 } // OHOS