• 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 #include "param_wrapper.h"
21 
22 namespace {
23     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerCodecCtrl"};
24 }
25 
26 namespace OHOS {
27 namespace Media {
28 constexpr uint32_t MAX_SOFT_BUFFERS = 10;
29 constexpr uint32_t DEFAULT_CACHE_BUFFERS = 1;
30 
PlayerCodecCtrl()31 PlayerCodecCtrl::PlayerCodecCtrl()
32 {
33     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
34     DisablePerformanceBySysParam();
35 }
36 
~PlayerCodecCtrl()37 PlayerCodecCtrl::~PlayerCodecCtrl()
38 {
39     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
40     notifier_ = nullptr;
41     elementMap_.clear();
42 }
43 
SetupCodecCb(const std::string & metaStr,GstElement * src,GstElement * videoSink,CapsFixErrorNotifier notifier)44 void PlayerCodecCtrl::SetupCodecCb(const std::string &metaStr, GstElement *src, GstElement *videoSink,
45     CapsFixErrorNotifier notifier)
46 {
47     if (metaStr.find("Codec/Decoder/Video/Hardware") != std::string::npos) {
48         // hardware dec
49         isHardwareDec_ = true;
50         notifier_ = notifier;
51         DecoderElement element;
52         element.isHardware = true;
53         element.signalId = g_signal_connect(src, "caps-fix-error", G_CALLBACK(&PlayerCodecCtrl::CapsFixErrorCb), this);
54         elementMap_[src] = element;
55         MEDIA_LOGD("add decoder element size = %{public}zu", elementMap_.size());
56         g_object_set(G_OBJECT(src), "player-mode", TRUE, nullptr);
57         if (!codecTypeList_.empty()) {
58             // For hls scene when change codec, the second codec should not go performance mode process.
59             codecTypeList_.push_back(true);
60             return;
61         }
62         // For performance mode.
63         codecTypeList_.push_back(true);
64 
65         g_object_set(G_OBJECT(src), "player-scene", TRUE, nullptr);
66         if (isEnablePerformanceMode_) {
67             g_object_set(G_OBJECT(src), "performance-mode", TRUE, nullptr);
68             g_object_set(G_OBJECT(videoSink), "performance-mode", TRUE, nullptr);
69         }
70 
71         GstCaps *caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", nullptr);
72         g_object_set(G_OBJECT(videoSink), "caps", caps, nullptr);
73         g_object_set(G_OBJECT(src), "sink-caps", caps, nullptr);
74         gst_caps_unref(caps);
75 
76         GstBufferPool *pool;
77         g_object_get(videoSink, "surface-pool", &pool, nullptr);
78         g_object_set(G_OBJECT(src), "surface-pool", pool, nullptr);
79     } else if (metaStr.find("Codec/Decoder/Video") != std::string::npos) {
80         // software dec
81         codecTypeList_.push_back(false);
82         isHardwareDec_ = false;
83     }
84 }
85 
DetectCodecSetup(const std::string & metaStr,GstElement * src,GstElement * videoSink,CapsFixErrorNotifier notifier)86 void PlayerCodecCtrl::DetectCodecSetup(const std::string &metaStr, GstElement *src, GstElement *videoSink,
87     CapsFixErrorNotifier notifier)
88 {
89     std::lock_guard<std::mutex> lock(mutex_);
90     MEDIA_LOGD("Codec Setup");
91     SetupCodecCb(metaStr, src, videoSink, notifier);
92     if (IsFirstCodecSetup()) {
93         SetupCodecBufferNum(metaStr, videoSink);
94         MEDIA_LOGI("0x%{public}06" PRIXPTR " Set isHardwareDec_ %{public}d", FAKE_POINTER(this), isHardwareDec_);
95         g_object_set(videoSink, "is-hardware-decoder", isHardwareDec_, nullptr);
96         isHEBCMode_ = isHardwareDec_;
97     }
98 }
99 
SetupCodecBufferNum(const std::string & metaStr,GstElement * src) const100 void PlayerCodecCtrl::SetupCodecBufferNum(const std::string &metaStr, GstElement *src) const
101 {
102     if (metaStr.find("Sink/Video") != std::string::npos && !isHardwareDec_) {
103         g_object_set(G_OBJECT(src), "max-pool-capacity", MAX_SOFT_BUFFERS, nullptr);
104         g_object_set(G_OBJECT(src), "cache-buffers-num", DEFAULT_CACHE_BUFFERS, nullptr);
105     }
106 }
107 
CapsFixErrorCb(const GstElement * decoder,gpointer userData)108 void PlayerCodecCtrl::CapsFixErrorCb(const GstElement *decoder, gpointer userData)
109 {
110     CHECK_AND_RETURN_LOG(decoder != nullptr, "decoder is nullptr");
111     CHECK_AND_RETURN_LOG(userData != nullptr, "userData is nullptr");
112     MEDIA_LOGD("CapsFixErrorCb in");
113 
114     auto playerCodecCtrl = static_cast<PlayerCodecCtrl *>(userData);
115     if (playerCodecCtrl->notifier_ != nullptr) {
116         playerCodecCtrl->notifier_();
117     }
118 }
119 
DetectCodecUnSetup(GstElement * src,GstElement * videoSink)120 void PlayerCodecCtrl::DetectCodecUnSetup(GstElement *src, GstElement *videoSink)
121 {
122     std::lock_guard<std::mutex> lock(mutex_);
123     MEDIA_LOGD("Codec UnSetup");
124     auto it = elementMap_.find(src);
125     if (it != elementMap_.end()) {
126         if (elementMap_[src].signalId != 0) {
127             g_signal_handler_disconnect(src, elementMap_[src].signalId);
128             elementMap_[src].signalId = 0;
129         }
130         elementMap_.erase(it);
131     }
132     MEDIA_LOGD("del decoder element size = %{public}zu", elementMap_.size());
133     HlsSwichSoftAndHardCodec(videoSink);
134 }
135 
HlsSwichSoftAndHardCodec(GstElement * videoSink)136 void PlayerCodecCtrl::HlsSwichSoftAndHardCodec(GstElement *videoSink)
137 {
138     CHECK_AND_RETURN_LOG(!codecTypeList_.empty(), "codec type list is empty");
139 
140     bool codecType = codecTypeList_.front();
141     codecTypeList_.pop_front();
142     if ((codecTypeList_.empty()) || (codecType == codecTypeList_.front())) {
143         MEDIA_LOGD("codec type is empty or the next is same");
144         return;
145     }
146 
147     GstCaps *caps = nullptr;
148     if (codecTypeList_.front()) {
149         caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", nullptr);
150         g_object_set(G_OBJECT(videoSink), "max-pool-capacity", SURFACE_MAX_QUEUE_SIZE, nullptr);
151         g_object_set(G_OBJECT(videoSink), "cache-buffers-num", 0, nullptr);
152     } else {
153         caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "RGBA", nullptr);
154         g_object_set(G_OBJECT(videoSink), "max-pool-capacity", MAX_SOFT_BUFFERS, nullptr);
155         g_object_set(G_OBJECT(videoSink), "cache-buffers-num", DEFAULT_CACHE_BUFFERS, nullptr);
156     }
157     MEDIA_LOGI("Set isHardwareDec_ %{public}d", codecTypeList_.front());
158     g_object_set(videoSink, "is-hardware-decoder", codecTypeList_.front(), nullptr);
159     isHEBCMode_ = codecTypeList_.front();
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     MEDIA_LOGD("EnhanceSeekPerformance %{public}d", enable);
168     for (auto &it : elementMap_) {
169         if (it.second.isHardware) {
170             g_object_set(it.first, "seeking", enable, nullptr);
171         }
172     }
173 }
174 
GetHEBCMode() const175 int32_t PlayerCodecCtrl::GetHEBCMode() const
176 {
177     return isHEBCMode_;
178 }
179 
IsFirstCodecSetup() const180 bool PlayerCodecCtrl::IsFirstCodecSetup() const
181 {
182     return codecTypeList_.size() == 1;
183 }
184 
HandleCodecBuffers(bool enable)185 int32_t PlayerCodecCtrl::HandleCodecBuffers(bool enable)
186 {
187     std::lock_guard<std::mutex> lock(mutex_);
188     MEDIA_LOGD("HandleCodecBuffers %{public}d", enable);
189     for (auto &it : elementMap_) {
190         if (it.second.isHardware) {
191             if (enable) {
192                 g_object_set(it.first, "free_codec_buffers", enable, nullptr);
193             } else {
194                 g_object_set(it.first, "recover_codec_buffers", enable, nullptr);
195             }
196             return MSERR_OK;
197         }
198     }
199     return MSERR_INVALID_OPERATION;
200 }
201 
StopFormatChange()202 void PlayerCodecCtrl::StopFormatChange()
203 {
204     std::lock_guard<std::mutex> lock(mutex_);
205     MEDIA_LOGD("StopFormatChange");
206     for (auto &it : elementMap_) {
207         if (it.second.isHardware) {
208             g_object_set(it.first, "stop-format-change", TRUE, nullptr);
209         }
210     }
211 }
DisablePerformanceBySysParam()212 void PlayerCodecCtrl::DisablePerformanceBySysParam()
213 {
214     std::string cmd;
215     int32_t ret = OHOS::system::GetStringParameter("sys.media.player.performance.enable", cmd, "");
216     if (ret == 0 && !cmd.empty()) {
217         isEnablePerformanceMode_ = cmd == "FALSE" ? false : true;
218     }
219 }
220 } // Media
221 } // OHOS