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