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/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 = (uint8_t *)malloc(inputSize);
64 (void)memset_s(outDataPtr, INPUT_BUFFER_SIZE, 0, inputSize);
65 if (readPos + INPUT_BUFFER_SIZE > testDataSize) {
66 inputSize = testDataSize - readPos;
67 }
68 (void)memcpy_s(outDataPtr, INPUT_BUFFER_SIZE, &testData[0] + readPos / sizeof(uint32_t), inputSize);
69 readPos += inputSize;
70 MEDIA_LOG_I("readPo:" PUBLIC_LOG_U32, readPos);
71 *getDataSize = inputSize;
72 return outDataPtr;
73 }
74
75 bool g_playFinished = false;
76
DataProcessThread()77 void DataProcessThread()
78 {
79 MEDIA_LOG_I("DataProcessThread in");
80 while (!g_playFinished) {
81 int8_t sourceFlag = -1;
82 uint32_t realGetSize = 0;
83 uint8_t *sourceData = GetDataFromSource(&sourceFlag, &realGetSize);
84 std::shared_ptr<DataBuffer> buffer;
85 (void) stream->GetEmptyBuffer(buffer);
86 if (buffer == nullptr) {
87 MEDIA_LOG_E("buffer null error.");
88 if (sourceData != nullptr) {
89 free(sourceData);
90 }
91 return;
92 } else {
93 MEDIA_LOG_I("realGetSize:" PUBLIC_LOG_U32, realGetSize);
94 if (sourceData != nullptr) { // get data
95 (void) memcpy_s(buffer->GetAddress(), buffer->GetCapacity(), sourceData, realGetSize);
96 buffer->SetSize(realGetSize);
97 free(sourceData);
98 } else { // not get data, must be eos
99 buffer->SetSize(0);
100 FALSE_LOG(sourceFlag == SOURCE_EOS);
101 MEDIA_LOG_I("SourceEos");
102 buffer->SetEos(true);
103 stream->QueueDataBuffer(buffer);
104 break;
105 }
106 stream->QueueDataBuffer(buffer);
107 }
108 }
109 task->StopAsync();
110 }
111
112 class PlayerCallbackImpl : public PlayerCallback {
OnPlaybackComplete()113 void OnPlaybackComplete() override
114 {
115 g_playFinished = true;
116 MEDIA_LOG_I("OnPlaybackComplete called, g_playFinished is true now.");
117 }
OnError(int32_t errorType,int32_t errorCode)118 void OnError(int32_t errorType, int32_t errorCode) override
119 {
120 }
OnInfo(int type,int extra)121 void OnInfo(int type, int extra) override
122 {
123 }
OnVideoSizeChanged(int width,int height)124 void OnVideoSizeChanged(int width, int height) override
125 {
126 }
OnRewindToComplete()127 void OnRewindToComplete() override
128 {
129 }
130 };
131
ReadDataFromFile(std::string dataPath)132 int ReadDataFromFile(std::string dataPath)
133 {
134 std::string dataFullPath;
135 if (OSAL::ConvertFullPath(dataPath, dataFullPath) && !dataFullPath.empty()) {
136 dataPath = dataFullPath;
137 }
138 std::fstream fs(dataPath);
139 if (!fs.is_open()) {
140 std::cout << "failed to open " << dataPath << '\n';
141 return 0;
142 }
143 std::stringstream ss;
144 while (!fs.eof()) {
145 std::string s;
146 fs >> s;
147 ss << s;
148 }
149 std::string data = ss.str();
150 const char* split = ",";
151 char* s_input = (char *)data.c_str();
152 char* p = strtok(s_input, split);
153 while (p != nullptr) {
154 uint32_t data;
155 (void)sscanf_s(p, "%x", &data);
156 testData.push_back(data);
157 p=strtok(nullptr, split);
158 }
159 return testData.size() * 4; // 4
160 }
161
StartLiteStreamPlayer(const std::string & dataPath)162 int StartLiteStreamPlayer(const std::string& dataPath)
163 {
164 MEDIA_LOG_I("Use media_lite interface player.");
165 g_playFinished = false;
166 auto player = OHOS::Media::CreateHiPlayer();
167 player->Init();
168 auto callback = std::make_shared<PlayerCallbackImpl>();
169 player->SetPlayerCallback(callback);
170 stream = CreateDataStream(INPUT_BUFFER_SIZE, INPUT_BUFFER_ITEM);
171 if (stream == nullptr) {
172 MEDIA_LOG_E("Create data stream fail.");
173 return -1;
174 }
175 OHOS::Media::Source source(stream);
176 player->SetSource(source);
177 player->SetLoop(false);
178 testDataSize = ReadDataFromFile(dataPath);
179 if (!testDataSize) {
180 MEDIA_LOG_E("Get data size fail.");
181 return -1;
182 }
183 MEDIA_LOG_I("testDataSize:" PUBLIC_LOG_U32, testDataSize);
184 task = std::make_shared<OSAL::Task>("DataProcessThread");
185 task->RegisterHandler(DataProcessThread);
186 task->Start();
187 player->Prepare();
188 player->Play();
189 while (!g_playFinished) {
190 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100
191 MEDIA_LOG_I("stream player thread running...");
192 }
193 readPos = 0;
194 stream = nullptr;
195 return 0;
196 }
197 #endif