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