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 38using namespace OHOS::Media; 39 40#define INPUT_BUFFER_SIZE 10 * 1024 41#define INPUT_BUFFER_ITEM 3 42 43static uint32_t readPos = 0; 44std::vector<uint32_t> testData; 45uint32_t testDataSize = 0; 46std::shared_ptr<DataStream> stream = nullptr; 47std::shared_ptr<OSAL::Task> task = nullptr; 48 49enum SourceFlag { 50 SOURCE_EOS, 51}; 52 53uint8_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 76bool g_playFinished = false; 77 78void 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 113class PlayerCallbackImpl : public PlayerCallback { 114 void OnPlaybackComplete() override 115 { 116 g_playFinished = true; 117 MEDIA_LOG_I("OnPlaybackComplete called, g_playFinished is true now."); 118 } 119 void OnError(int32_t errorType, int32_t errorCode) override 120 { 121 } 122 void OnInfo(int type, int extra) override 123 { 124 } 125 void OnVideoSizeChanged(int width, int height) override 126 { 127 } 128 void OnRewindToComplete() override 129 { 130 } 131}; 132 133int 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 164int 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