1 /*
2 * Copyright (c) 2022-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 #ifdef OHOS_LITE
16 #define HST_LOG_TAG "LiteStreamPlayer"
17
18 #define LOG_TAG "main"
19
20 #include <chrono>
21 #include <cstring>
22 #include <cstdio>
23 #include <fstream>
24 #include <iostream>
25 #include <memory>
26 #include <sstream>
27 #include <string>
28 #include <thread>
29 #include <vector>
30
31 #include "scene/lite/hiplayer.h"
32 #include "securec.h"
33 #include "foundation/log.h"
34 #include "foundation/multimedia/media_utils_lite/interfaces/kits/data_stream.h"
35 #include "foundation/osal/utils/util.h"
36 #include "foundation/osal/thread/task.h"
37
38 using namespace OHOS::Media;
39
40 #define INPUT_BUFFER_SIZE 10 * 1024
41 #define INPUT_BUFFER_ITEM 3
42
43 static uint32_t readPos = 0;
44 std::vector<uint32_t> testData;
45 uint32_t testDataSize = 0;
46 std::shared_ptr<DataStream> stream = nullptr;
47 std::shared_ptr<OSAL::Task> task = nullptr;
48
49 enum SourceFlag {
50 SOURCE_EOS,
51 };
52
GetDataFromSource(int8_t * flag,uint32_t * getDataSize)53 uint8_t *GetDataFromSource(int8_t *flag, uint32_t *getDataSize)
54 {
55 uint32_t inputSize = INPUT_BUFFER_SIZE;
56 MEDIA_LOG_I("testDataSize:" PUBLIC_LOG_U32 " ,readPos:" PUBLIC_LOG_U32, testDataSize, readPos);
57 uint8_t *outDataPtr = nullptr;
58 if (readPos == testDataSize) {
59 *flag = SOURCE_EOS;
60 *getDataSize = 0;
61 return outDataPtr;
62 }
63 outDataPtr = reinterpret_cast<uint8_t*>(malloc(inputSize));
64 auto ret = memset_s(outDataPtr, INPUT_BUFFER_SIZE, 0, inputSize);
65 FALSE_RETURN(ret == 0);
66 if (readPos + INPUT_BUFFER_SIZE > testDataSize) {
67 inputSize = testDataSize - readPos;
68 }
69 (void)memcpy_s(outDataPtr, INPUT_BUFFER_SIZE, &testData[0] + readPos / sizeof(uint32_t), inputSize);
70 readPos += inputSize;
71 MEDIA_LOG_I("readPo:" PUBLIC_LOG_U32, readPos);
72 *getDataSize = inputSize;
73 return outDataPtr;
74 }
75
76 bool g_playFinished = false;
77
DataProcessThread()78 void DataProcessThread()
79 {
80 MEDIA_LOG_I("DataProcessThread in");
81 while (!g_playFinished) {
82 int8_t sourceFlag = -1;
83 uint32_t realGetSize = 0;
84 uint8_t *sourceData = GetDataFromSource(&sourceFlag, &realGetSize);
85 std::shared_ptr<DataBuffer> buffer;
86 (void) stream->GetEmptyBuffer(buffer);
87 if (buffer == nullptr) {
88 MEDIA_LOG_E("buffer null error.");
89 if (sourceData != nullptr) {
90 free(sourceData);
91 }
92 return;
93 } else {
94 MEDIA_LOG_I("realGetSize:" PUBLIC_LOG_U32, realGetSize);
95 if (sourceData != nullptr) { // get data
96 (void) memcpy_s(buffer->GetAddress(), buffer->GetCapacity(), sourceData, realGetSize);
97 buffer->SetSize(realGetSize);
98 free(sourceData);
99 } else { // not get data, must be eos
100 buffer->SetSize(0);
101 FALSE_LOG(sourceFlag == SOURCE_EOS);
102 MEDIA_LOG_I("SourceEos");
103 buffer->SetEos(true);
104 stream->QueueDataBuffer(buffer);
105 break;
106 }
107 stream->QueueDataBuffer(buffer);
108 }
109 }
110 task->StopAsync();
111 }
112
113 class PlayerCallbackImpl : public PlayerCallback {
OnPlaybackComplete()114 void OnPlaybackComplete() override
115 {
116 g_playFinished = true;
117 MEDIA_LOG_I("OnPlaybackComplete called, g_playFinished is true now.");
118 }
OnError(int32_t errorType,int32_t errorCode)119 void OnError(int32_t errorType, int32_t errorCode) override
120 {
121 }
OnInfo(int type,int extra)122 void OnInfo(int type, int extra) override
123 {
124 }
OnVideoSizeChanged(int width,int height)125 void OnVideoSizeChanged(int width, int height) override
126 {
127 }
OnRewindToComplete()128 void OnRewindToComplete() override
129 {
130 }
131 };
132
ReadDataFromFile(std::string dataPath)133 int ReadDataFromFile(std::string dataPath)
134 {
135 std::string dataFullPath;
136 if (OSAL::ConvertFullPath(dataPath, dataFullPath) && !dataFullPath.empty()) {
137 dataPath = dataFullPath;
138 }
139 std::fstream fs(dataPath);
140 if (!fs.is_open()) {
141 std::cout << "failed to open " << dataPath << '\n';
142 return 0;
143 }
144 std::stringstream ss;
145 while (!fs.eof()) {
146 std::string s;
147 fs >> s;
148 ss << s;
149 }
150 std::string data = ss.str();
151 const char* split = ",";
152 char* s_input = data.c_str();
153 char* p = strtok(s_input, split);
154 while (p != nullptr) {
155 uint32_t dataValue;
156 auto ret = sscanf_s(p, "%x", &dataValue);
157 FALSE_LOG_MSG_W(ret == 0, "sscanf_s failed.");
158 testData.push_back(dataValue);
159 p=strtok(nullptr, split);
160 }
161 return testData.size() * 4; // 4
162 }
163
StartLiteStreamPlayer(const std::string & dataPath)164 int StartLiteStreamPlayer(const std::string& dataPath)
165 {
166 MEDIA_LOG_I("Use media_lite interface player.");
167 g_playFinished = false;
168 auto player = OHOS::Media::CreateHiPlayer();
169 player->Init();
170 auto callback = std::make_shared<PlayerCallbackImpl>();
171 player->SetPlayerCallback(callback);
172 stream = CreateDataStream(INPUT_BUFFER_SIZE, INPUT_BUFFER_ITEM);
173 if (stream == nullptr) {
174 MEDIA_LOG_E("Create data stream fail.");
175 return -1;
176 }
177 OHOS::Media::Source source(stream);
178 player->SetSource(source);
179 player->SetLoop(false);
180 testDataSize = ReadDataFromFile(dataPath);
181 if (!testDataSize) {
182 MEDIA_LOG_E("Get data size fail.");
183 return -1;
184 }
185 MEDIA_LOG_I("testDataSize:" PUBLIC_LOG_U32, testDataSize);
186 task = std::make_shared<OSAL::Task>("DataProcessThread");
187 task->RegisterHandler(DataProcessThread);
188 task->Start();
189 player->Prepare();
190 player->Play();
191 while (!g_playFinished) {
192 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100
193 MEDIA_LOG_I("stream player thread running...");
194 }
195 readPos = 0;
196 stream = nullptr;
197 return 0;
198 }
199 #endif