diff --git a/media/BUILD.gn b/media/BUILD.gn index 01f99e1ac2988557b7e3dbc8de795ce0996aca54..5a95f70ffdc3053b33b51a2553e15eceeac7450e 100755 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -29,6 +29,22 @@ executable("camera_sample") { output_dir = "$root_out_dir/dev_tools" } +executable("audio_capture_sample") { + sources = [ + "audio_capture_sample.cpp", + ] + cflags = ["-Wall"] + cflags_cc = cflags + + ldflags = ["-lstdc++"] + ldflags += ["-lpthread"] + ldflags += ["-Wl,-rpath-link=$ohos_root_path/$root_out_dir"] + deps = [ + "//third_party/bounds_checking_function:libsec_shared", + "//foundation/multimedia/audio_lite/frameworks:audio_capturer_lite", + ] + output_dir = "$root_out_dir/dev_tools" +} executable("player_sample") { sources = [ "player_sample.cpp" ] cflags = [ "-Wall" ] @@ -48,5 +64,6 @@ lite_component("media_sample") { features = [ ":camera_sample", ":player_sample", + ":audio_capture_sample", ] } diff --git a/media/audio_capture_sample.cpp b/media/audio_capture_sample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd3366f3f4b68d8345077165fa86f61bfbc93e53 --- /dev/null +++ b/media/audio_capture_sample.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "audio_capturer.h" +#include "media_errors.h" +#include "securec.h" + +using namespace OHOS; +using namespace OHOS::Audio; +using namespace OHOS::Media; +using namespace std; + +struct AudioSourceInput { + size_t framesize; + uint8_t *buffer; + AudioCapturer *audioCap; + AudioCodecFormat audioFormat; + std::thread processThread; + bool bThreadRun; +}; + +enum AppState { + AV_ON, + AV_OFF +}; + +static AudioSourceInput g_audioSourceProcessInput; + +static char *GernerateFileName(AudioCodecFormat format) +{ + time_t stCurrent; + char aszDatetime[0x100]; + (void)time(&stCurrent); + struct tm *pstCurrentTime = localtime(&(stCurrent)); + if (pstCurrentTime == nullptr) { + return nullptr; + } + if (strftime(aszDatetime, 0x100, "%Y-%m-%d-%H-%M-%S", pstCurrentTime) > 0) { + std::cout << "Current Time: " << aszDatetime << std::endl; + } + + string postfix; + switch (format) { + case PCM: + postfix = "pcm"; + break; + case AAC_LC: + postfix = "aac"; + break; + case G711A: + postfix = "g711a"; + break; + case G711U: + postfix = "g711u"; + break; + case G726: + postfix = "g726"; + break; + default: + return nullptr; + } + + const int32_t size = 0x180; + char *name = static_cast(malloc(size)); + if (name == nullptr) { + return nullptr; + } + (void)memset_s(name, size, 0, size); + /* create file for save stream */ + if (snprintf_s(name, size, size - 1, "/sdcard/audio_%s.%s", aszDatetime, postfix.c_str()) < 0) { + std::cout << "snprintf_s failed " << std::endl; + free(name); + return nullptr; + } + return name; +} + +static void AudioInputSourceProcess(AudioSourceInput *audioSourceInput) +{ + std::cout << "audioSourceInput: " << audioSourceInput << std::endl; + if (audioSourceInput == nullptr) { + return; + } + + char *fileName = GernerateFileName(audioSourceInput->audioFormat); + if (fileName == nullptr) { + return; + } + + FILE *pfd = fopen(fileName, "w+"); + if (pfd == nullptr) { + std::cout << "open file failed " << fileName << std::endl; + free(fileName); + return; + } + std::cout << "Open SUCCESS " << fileName << std::endl; + int readCnt = 0; + while (audioSourceInput->bThreadRun) { + int ret = audioSourceInput->audioCap->Read(audioSourceInput->buffer, + audioSourceInput->framesize, false); + if (ret == -1) { + std::cout << "audioCap Read failed ret:" << ret << std::endl; + continue; + } + if (fwrite(audioSourceInput->buffer, 1, ret, pfd) != ret) { + std::cout << "fwrite failed errno:"<< errno << std::endl; + break; + } + readCnt++; + std::cout << "audioCap Read readCnt: "<< readCnt << " size: " << ret << std::endl; + } + (void)fclose(pfd); + free(fileName); +} + +struct CapturerInfo { + AudioCodecFormat audioFormat; + int32_t sampleRate; + int32_t bitRate; +}; + +static AudioCodecFormat GetAudioFormat(void) +{ + std::cout << "*******************************************" << endl; + std::cout << "SetCapturerInfo (PCM:1, AAC_LC:2, G711A:7, G711U:8, G726:9)" << endl; + std::cout << "*******************************************" << endl; + int32_t audioFormat; + std::cin >> audioFormat; + cout << "input audioFormat:" << audioFormat << endl; + if (audioFormat != 1 && audioFormat != 0x2 && audioFormat != 0x7 && + audioFormat != 0x8 && audioFormat != 0x9) { + std::cout << "Can't support input format:" << static_cast (audioFormat) << std::endl; + return FORMAT_BUTT; + } + return static_cast (audioFormat); +} + +static void GetDefaultSampleRateAndRateBaseFormat(AudioCodecFormat format, int32_t &sr, int32_t &rate) +{ + const CapturerInfo audioCapturerInfo[] = { + {PCM, 16000, 128000}, + {AAC_LC, 48000, 128000}, + {G711A, 8000, 64000}, + {G711U, 8000, 64000}, + {G726, 8000, 24000} + }; + + int validCapInfoNum = sizeof(audioCapturerInfo) / sizeof(audioCapturerInfo[0]); + for (int i = 0; i < validCapInfoNum; i++) { + if (format == audioCapturerInfo[i].audioFormat) { + sr = audioCapturerInfo[i].sampleRate; + rate = audioCapturerInfo[i].bitRate; + } + } +} + +static int32_t GetChannelCount(void) +{ + std::cout << "*******************************************" << endl; + std::cout << "SetCapturerInfo (channelCount:1, channelCount:2)" << endl; + std::cout << "*******************************************" << endl; + int32_t channelCount; + std::cin >> channelCount; + if (channelCount != 1 && channelCount != 0x2) { + std::cout << "Can't support input channelCount:" << channelCount << std::endl; + return -1; + } + return channelCount; +} + +static void ShowCmdInfo(void) +{ + cout << "*******************************************" << endl; + cout << "Select the behavior of audio capturer." << endl; + cout << "s or S-----start audio capturer" << endl; + cout << "p or P-----stop audio capturer" << endl; + cout << "q or Q-----quit audio capturer" << endl; + cout << "*******************************************" << endl; +} + +static void TaskQuit(AudioCapturer &audioCap, AppState &state) +{ + if (state == AV_ON) { + g_audioSourceProcessInput.bThreadRun = false; + g_audioSourceProcessInput.processThread.join(); + if (!audioCap.Stop()) { + std::cout << "Stop audioCap failed, quit record\n" << endl; + } + state = AV_OFF; + } +} + +static int32_t TaskStop(AudioCapturer &audioCap, AppState &state) +{ + if (state == AV_ON) { + g_audioSourceProcessInput.bThreadRun = false; + g_audioSourceProcessInput.processThread.join(); + if (!audioCap.Stop()) { + std::cout << "Stop audioCap fialed, stop record " << endl; + return -1; + } + state = AV_OFF; + } else { + std::cout << "Start recorder first." << endl; + } + return 0; +} + +static int32_t TaskStart(AudioCapturer &audioCap, AppState &state) +{ + if (state == AV_ON) { + return 0; + } + + if (!audioCap.Start()) { + std::cout << "Can't Start..." << endl; + delete g_audioSourceProcessInput.buffer; + return -1; + } + g_audioSourceProcessInput.audioCap = &audioCap; + g_audioSourceProcessInput.bThreadRun = true; + g_audioSourceProcessInput.processThread = std::thread(AudioInputSourceProcess, + &g_audioSourceProcessInput); + state = AV_ON; + std::cout << "Recording..." << endl; + return 0; +} + +static void RumCmd(AudioCapturer &audioCap) +{ + ShowCmdInfo(); + char input; + AppState state = AV_OFF; + while (std::cin >> input) { + switch (input) { + case 's': + case 'S': + if (TaskStart(audioCap, state) != 0) { + return; + } + break; + case 'p': + case 'P': + if (TaskStop(audioCap, state) != 0) { + return; + } + break; + case 'q': + case 'Q': + TaskQuit(audioCap, state); + return; + default: + break; + } + } +} + +int main(int argc, char *argv[]) +{ + std::cout << "audio_capture_sample " << std::endl; + int ret = 0; + size_t frameCount; + AudioCapturer audioCap; + + AudioCapturerInfo info; + info.inputSource = AUDIO_MIC; + info.bitWidth = BIT_WIDTH_16; + AudioCodecFormat audioFormat = GetAudioFormat(); + if (audioFormat == FORMAT_BUTT) { + return -1; + } + info.audioFormat = audioFormat; + g_audioSourceProcessInput.audioFormat = audioFormat; + GetDefaultSampleRateAndRateBaseFormat(audioFormat, info.sampleRate, info.bitRate); + + info.channelCount = GetChannelCount(); + if (info.channelCount == -1) { + return -1; + } + + std::cout << " SetCapturerInfo" << std::endl; + if ((ret = audioCap.SetCapturerInfo(info)) != 0) { + std::cout << "Can't SetCapturerInfo " << std::endl; + delete g_audioSourceProcessInput.buffer; + return -1; + } + frameCount = audioCap.GetFrameCount(); + std::cout << "GetFrameCount " << frameCount << std::endl; + g_audioSourceProcessInput.framesize = frameCount * 0x400; + g_audioSourceProcessInput.buffer = new uint8_t[g_audioSourceProcessInput.framesize]; + + RumCmd(audioCap); +EXIT: + audioCap.Release(); + delete g_audioSourceProcessInput.buffer; + g_audioSourceProcessInput.buffer = nullptr; + return 0; +} diff --git a/media/player_sample.cpp b/media/player_sample.cpp index b6739b979f83f17601d1b75f39c6375b93366444..b6b8675482622c01aef446723678113c413fcffd 100755 --- a/media/player_sample.cpp +++ b/media/player_sample.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -42,64 +42,54 @@ using OHOS::Media::StreamSource; using OHOS::Media::StreamCallback; using namespace OHOS::Media; -#define DOFUNC_STR_NORET(func , str) \ - do { \ - HI_S32 s32Ret = 0; \ - s32Ret = func; \ - if(s32Ret != 0) \ - { \ - printf("[liteplayer_sample][%s:%d] ret:%d, %s \n", __FILE__, __LINE__, s32Ret,str); \ - return NULL;\ - } \ - } while (0) - -#define DOFUNC_STR_RET(func , str) \ - do { \ - HI_S32 s32Ret = 0; \ - s32Ret = func; \ - if(s32Ret != 0) \ - { \ - printf("[liteplayer_sample][%s:%d] ret:%d, %s \n", __FILE__, __LINE__, s32Ret,str); \ - return -1;\ - } \ - } while (0) - -#define IS_OK(ret) \ -do { \ - if (ret != 0) { \ - printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); \ - } \ -} while (0) - -#define SAMPLE_RETURN_VAL_IF_NULL(condition) \ - do { \ - if ((condition) == nullptr) { \ - printf("" #condition " is NULL error %s %d\n", __FUNCTION__, __LINE__); \ - return -1; \ - } \ - } while (0) +static int64_t GetCurTimeUs() +{ + const int32_t SS2US = 1000000; + struct timeval ts; + ts.tv_sec = 0; + ts.tv_usec = 0; + gettimeofday(&ts, nullptr); + return (static_cast (ts.tv_sec) * SS2US) + static_cast (ts.tv_usec); +} -class StreamSourceSample; -typedef struct TagTestSample +static int64_t GetCurTimeMs() { + const int32_t US2MS = 1000; + int64_t curTimeUs = GetCurTimeUs(); + return static_cast(curTimeUs / US2MS); +} + +class StreamSourceSample; +struct TestSample { std::shared_ptr adapter; pthread_t process; pthread_mutex_t mutex; - int32_t isThreadRunning; + bool isThreadRunning; int32_t sourceType; - char filePath[PATH_MAX]; + char filePath[PATH_MAX + 1]; + int64_t fileSize; int32_t pauseAfterPlay; + Surface *surface; std::shared_ptr streamSample; -} TestSample; + std::shared_ptr cb; + int64_t newPlayerCost; + int64_t setSourceCost; + int64_t prepareCost; + int64_t setSurfaceCost; + int64_t playCost; + int64_t RewindCost; + int64_t RewindBegin; + int64_t stopCost; + int64_t releaseCost; +}; -typedef struct TagIdleBuffer{ +struct IdleBuffer { size_t idx; size_t offset; size_t size; -} IdleBuffer; +}; -class StreamSourceSample :public StreamSource -{ +class StreamSourceSample : public StreamSource { public: StreamSourceSample(void); virtual ~StreamSourceSample(void); @@ -107,7 +97,7 @@ public: void SetStreamCallback(const std::shared_ptr &callback); uint8_t *GetBufferAddress(size_t idx); void QueueBuffer(size_t index, size_t offset, size_t size, int64_t timestampUs, uint32_t flags); - int GetAvailableBuffer(IdleBuffer* buffer); + int GetAvailableBuffer(IdleBuffer *buffer); private: std::weak_ptr m_callBack; @@ -163,7 +153,10 @@ void StreamSourceSample::OnBufferAvailable(size_t index, size_t offset, size_t s int StreamSourceSample::GetAvailableBuffer(IdleBuffer* buffer) { - SAMPLE_RETURN_VAL_IF_NULL(buffer); + if (buffer == nullptr) { + printf("buffer is nullptr error %s %d\n", __FUNCTION__, __LINE__); + return -1; + } pthread_mutex_lock(&m_mutex); if (aviableBuffer.empty()) { pthread_mutex_unlock(&m_mutex); @@ -175,22 +168,97 @@ int StreamSourceSample::GetAvailableBuffer(IdleBuffer* buffer) return 0; } -static void* streamProcess(void* arg) +class PlayerCallbackImpl : public PlayerCallback { +public: + PlayerCallbackImpl(TestSample &in); + ~PlayerCallbackImpl(); + void OnPlaybackComplete(); + void OnError(int32_t errorType, int32_t errorCode); + void OnInfo(int type, int extra); + void OnVideoSizeChanged(int width, int height); + void OnRewindToComplete(); + +private: + TestSample *sample; +}; + +PlayerCallbackImpl::PlayerCallbackImpl(TestSample &in) +{ + sample = ∈ +} + +PlayerCallbackImpl::~PlayerCallbackImpl() +{ + printf("dtor\n"); +} + +void PlayerCallbackImpl::OnPlaybackComplete(void) +{ + printf("OnPlaybackComplete test\n"); +} + +void PlayerCallbackImpl::OnError(int32_t errorType, int32_t errorCode) +{ + printf("OnError test, errorType:%d, errorCode:%d\n", errorType, errorCode); +} + +void PlayerCallbackImpl::OnInfo(int type, int extra) +{ + printf("OnInfo test, type:%d, extra:%d\n", type, extra); +} + +void PlayerCallbackImpl::OnVideoSizeChanged(int width, int height) +{ + printf("OnVideoSizeChanged test width:%d, height:%d\n", width, height); +} + +void PlayerCallbackImpl::OnRewindToComplete(void) +{ + sample->RewindCost = GetCurTimeMs() - sample->RewindBegin; + printf("OnRewindToComplete test\n"); +} + +static void CostTestPrintf(TestSample &sample) +{ + printf("\n\n\n##################player cost info begin\n"); + + printf("start cost total:%lld\n", sample.setSourceCost + sample.prepareCost + sample.setSurfaceCost + + sample.playCost); + printf("new player:%lld,\n setSourceCost:%lld,\n prepareCost:%lld,\n, setSurfaceCost:%lld,\n playCost:%lld,\n", + sample.newPlayerCost, sample.setSourceCost, sample.prepareCost, sample.setSurfaceCost, sample.playCost); + + printf("seek cost total:%lld\n", sample.RewindCost); + + printf("destory cost total:%lld\n", sample.stopCost + sample.releaseCost); + printf("stopCost:%lld,\n releaseCost:%lld,\n", sample.stopCost, sample.releaseCost); + + printf("##################player cost info end\n\n\n"); +} + +static void *streamProcess(void *arg) { + const int32_t STEAM_PROCESS_SLEEP_TIME_US = 20000; uint8_t *data = nullptr; size_t readLen; size_t bufferSize; TestSample *sample = (TestSample *)arg; FILE* pFile = fopen(sample->filePath, "rb"); - if (pFile == NULL) { - return NULL; + if (pFile == nullptr) { + return nullptr; } prctl(PR_SET_NAME, "StreamProc", 0, 0, 0); printf("[%s,%d] file:%s\n", __func__, __LINE__, sample->filePath); - while(sample->isThreadRunning) { + while (true) { + pthread_mutex_lock(&sample->mutex); + if (!sample->isThreadRunning) { + printf("[%s,%d] thread should exit\n", __func__, __LINE__); + pthread_mutex_unlock(&sample->mutex); + break; + } + pthread_mutex_unlock(&sample->mutex); data = sample->streamSample->GetSharedBuffer(bufferSize); if (data == nullptr) { - usleep(20000); + usleep(STEAM_PROCESS_SLEEP_TIME_US); continue; } readLen = fread(data, 1, bufferSize, pFile); @@ -203,173 +271,562 @@ static void* streamProcess(void* arg) } fclose(pFile); printf("[%s,%d]\n", __func__, __LINE__); - return NULL; + pthread_mutex_lock(&sample->mutex); + sample->isThreadRunning = false; + pthread_mutex_unlock(&sample->mutex); + return nullptr; } -static void SampleCmd(TestSample &sample) +static void GetFileSize(TestSample &sample) { - char cmd[64]; /* 64: Array length */ - int ret; - int64_t timeMs = 0; + sample.fileSize = -1; + if (sample.sourceType != 1 && sample.sourceType != 0) { + return; + } + + FILE *fileTmp = fopen(sample.filePath, "rb"); + if (fileTmp != nullptr) { + fseek(fileTmp, 0, SEEK_END); + sample.fileSize = ftell(fileTmp); + fclose(fileTmp); + fileTmp = nullptr; + } +} + +static int SetSurface(TestSample &sample) +{ + if (sample.surface != nullptr) { + return 0; + } + + int64_t begin = GetCurTimeMs(); + + sample.surface = Surface::CreateSurface(); + if (sample.surface == nullptr) { + printf("[%s,%d] CreateSurface failed\n", __func__, __LINE__); + return -1; + } + sample.surface->SetUserData("region_position_x", "0"); + sample.surface->SetUserData("region_position_y", "0"); + sample.surface->SetUserData("region_width", "480"); + sample.surface->SetUserData("region_height", "480"); + int32_t ret = sample.adapter->SetVideoSurface(sample.surface); + sample.setSurfaceCost = GetCurTimeMs() - begin; + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + return 0; +} + +static void DestorySurface(TestSample &sample) +{ + if (sample.surface != nullptr) { + delete(sample.surface); + sample.surface = nullptr; + } +} + +static int SetCallback(TestSample &sample) +{ + if (sample.cb == nullptr) { + sample.cb = std::make_shared(sample); + sample.adapter->SetPlayerCallback(sample.cb); + } + return 0; +} + +static void DestoryCallback(TestSample &sample) +{ + if (sample.cb != nullptr) { + sample.cb.reset(); + sample.cb = nullptr; + } +} + +static int SetStreamSourceProcess(TestSample &sample) +{ + sample.streamSample = std::make_shared(); + Format formats; + formats.PutStringValue(CODEC_MIME, MIME_AUDIO_AAC); + Source source(sample.streamSample, formats); + sample.adapter->SetSource(source); + sample.isThreadRunning = true; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 0x10000); + int32_t ret = pthread_create(&sample.process, &attr, streamProcess, &sample); + if (ret != 0) { + printf("pthread_create failed %d\n", ret); + sample.isThreadRunning = false; + return -1; + } + return 0; +} + +static int SetSourceProcess(TestSample &sample) +{ + int64_t begin = GetCurTimeMs(); + if (sample.sourceType == 1) { + std::string uri(sample.filePath); + std::map header; + Source source(uri, header); + sample.adapter->SetSource(source); + } else { + struct stat stFileState = {0}; + if (lstat(sample.filePath, &stFileState) != 0) { + printf("lstat %s failed, please check the file exist, errno:%d\n", sample.filePath, errno); + return -1; + } + if (SetStreamSourceProcess(sample) != 0) { + printf("SetStreamSourceProcess failed\n"); + return -1; + } + } + sample.setSourceCost = GetCurTimeMs() - begin; + return 0; +} + +static int PrepareProcess(TestSample &sample) +{ + int64_t begin = GetCurTimeMs(); + + if (sample.pauseAfterPlay != 0) { + Format formatSetPauseAfterPlay; + formatSetPauseAfterPlay.PutIntValue(PAUSE_AFTER_PLAY, true); + sample.adapter->SetParameter(formatSetPauseAfterPlay); + } + sample.adapter->Prepare(); + sample.prepareCost = GetCurTimeMs() - begin; + + SetCallback(sample); + SetSurface(sample); + return 0; +} + +static int PlayProcess(TestSample &sample) +{ + int32_t ret; + int64_t begin = GetCurTimeMs(); + + if (sample.pauseAfterPlay != 0) { + ret = sample.adapter->Pause(); + } else { + ret = sample.adapter->Play(); + } + sample.playCost = GetCurTimeMs() - begin; + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + return 0; +} + +static int ReleaseProcess(TestSample &sample) +{ + int32_t ret; + int64_t begin = GetCurTimeMs(); + + if (sample.pauseAfterPlay != 0) { + ret = sample.adapter->Pause(); + } else { + ret = sample.adapter->Play(); + } + sample.playCost = GetCurTimeMs() - begin; + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + return 0; +} + +static void EndStreamSourceThread(TestSample &sample) +{ + if (sample.sourceType == 0x2 && sample.process != -1) { + pthread_mutex_lock(&sample.mutex); + sample.isThreadRunning = false; + pthread_mutex_unlock(&sample.mutex); + pthread_join(sample.process, nullptr); + sample.process = -1; + } +} + +static int CreatePlayerProcess(TestSample &sample) +{ + SetSourceProcess(sample); + PrepareProcess(sample); + PlayProcess(sample); + return 0; +} + +static int ReplayProcess(TestSample &sample) +{ + EndStreamSourceThread(sample); + sample.adapter->Stop(); + + sample.adapter->Release(); + sample.adapter.reset(); + + DestorySurface(sample); + DestoryCallback(sample); + if (sample.sourceType == 0x2) { + sample.streamSample.reset(); + } + + sample.adapter = std::make_shared(); + + return CreatePlayerProcess(sample); +} + +static int PlayNextProcess(TestSample &sample) +{ + EndStreamSourceThread(sample); + sample.adapter->Stop(); + sample.adapter->Reset(); + DestorySurface(sample); + if (sample.sourceType == 0x2) { + sample.streamSample.reset(); + } + + return CreatePlayerProcess(sample); +} + +static int CostTest(TestSample &sample) +{ + if (sample.sourceType >= 0x2) { + return 0; + } + + int64_t begin; + int64_t end; + + EndStreamSourceThread(sample); + begin = GetCurTimeMs(); + sample.adapter->Stop(); + end = GetCurTimeMs(); + sample.stopCost = end - begin; + + begin = end; + sample.adapter->Release(); + sample.adapter.reset(); + sample.releaseCost = GetCurTimeMs() - begin; + + DestorySurface(sample); + DestoryCallback(sample); + if (sample.sourceType == 0x2) { + sample.streamSample.reset(); + } + CostTestPrintf(sample); + + begin = GetCurTimeMs(); + sample.adapter = std::make_shared(); + sample.newPlayerCost = GetCurTimeMs() - begin; + + CreatePlayerProcess(sample); + + sleep(0xa); // sleep 10s and seek + sample.RewindBegin = GetCurTimeMs(); + sample.adapter->Rewind(0, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC); + sleep(0x5); // sleep 5s after seek + return 0; +} + +static void RunCmdShow(TestSample &sample) +{ + printf("now show player info\n"); + + printf("player IsPlaying:%d IsSingleLooping:%d\n", sample.adapter->IsPlaying(), + sample.adapter->IsSingleLooping()); + int64_t duration; + int32_t ret = sample.adapter->GetDuration(duration); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + int64_t currentPosition; + ret = sample.adapter->GetCurrentTime(currentPosition); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + printf("player duration:%lld GetCurrentTime:%lld\n", duration, currentPosition); + int32_t videoWidth; int32_t videoHeight; + ret = sample.adapter->GetVideoWidth(videoWidth); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + ret = sample.adapter->GetVideoHeight(videoHeight); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + printf("player videoWidth:%d videoHeight:%d\n", videoWidth, videoHeight); + int32_t state; + ret = sample.adapter->GetPlayerState(state); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + printf("player current state:%d\n", state); +} + +static void RunCmdSetVolume(TestSample &sample, const char cmd[]) +{ float lvolume; float rvolume; - int loop = 0; + if (sscanf_s(cmd, "volume %f %f", &lvolume, &rvolume) != 0x2) { + printf("ERR: not input volume, example: volume 50 50!\n"); + return; + } + printf("try set volume %f %f\n", lvolume, rvolume); + int32_t ret = sample.adapter->SetVolume(lvolume, rvolume); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } +} + +static void RunCmdNext(TestSample &sample, const char cmd[]) +{ + int32_t cnt; + + if (sscanf_s(cmd, "next %d", &cnt) != 1) { + printf("ERR: not input next play count, example: next 10000!\n"); + return; + } + + while (cnt > 0) { + if (PlayNextProcess(sample) != 0) { + printf("PlayNextProcess process failed\n"); + return; + } + sleep(0x5); // sleep 5s and loop + cnt--; + }; +} + +static void RunCmdPressurePupl(TestSample &sample, const char cmd[]) +{ + int32_t cnt; + int ret; + + if (sscanf_s(cmd, "pressure_pupl %d", &cnt) != 1) { + printf("ERR: not input replay count, example: pressure 10000!\n"); + return; + } + while (cnt > 0) { + ret = sample.adapter->Pause(); + sleep(1); + ret = sample.adapter->Play(); + sleep(1); + cnt--; + } +} + +static void RunCmdPressureSeek(TestSample &sample, const char cmd[]) +{ + int32_t cnt; + int ret; + + if (sscanf_s(cmd, "pressure_seek %d", &cnt) != 1) { + printf("ERR: not input replay count, example: pressure 10000!\n"); + return; + } + if (sample.sourceType == 0x2) { + printf("ERR: streamsource not support pressure_seek\n"); + return; + } + + const int32_t rewindPos = 5000; + int64_t currentPosition; + while (cnt > 0) { + sample.adapter->Rewind(rewindPos, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC); + ret = sample.adapter->GetCurrentTime(currentPosition); + printf("##############player GetCurrentTime, ret:%d, time:%lld\n", ret, currentPosition); + sleep(0x2); + cnt--; + } +} + +static void RunCmdLoop(TestSample &sample, const char cmd[]) +{ + int32_t loop; + + if (sscanf_s(cmd, "loop %d", &loop) != 1) { + printf("ERR: not input loop flag, example: loop 1!\n"); + return; + } + + printf("try set loop %d\n", loop); + int32_t ret = sample.adapter->EnableSingleLooping(loop == 1); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } + printf("Set loop %d\n", loop); +} + +static void RunCmdSpeed(TestSample &sample, const char cmd[]) +{ + float speed = 1.0; + if (sscanf_s(cmd, "speed %f", &speed) != 1) { + printf("ERR: not input seek time, example: speed 1.0!\n"); + return; + } + + int32_t ret = sample.adapter->SetPlaybackSpeed(speed); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } +} + +static void RunCmdSeek(TestSample &sample, const char cmd[]) +{ + int64_t timeMs = 0; + if (sscanf_s(cmd, "seek %d", &timeMs) != 1) { + printf("ERR: not input seek time, example: seek 1000!\n"); + return; + } + + int32_t ret = sample.adapter->Rewind(timeMs, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC); + if (ret != 0) { + printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret); + } +} + +static void RunCmdSleep(const char cmd[]) +{ + int64_t timeS = 0; + if (sscanf_s(cmd, "sleep %d", &timeS) != 1) { + printf("ERR: not input replay count, example: sleep 100!\n"); + return; + } + sleep(timeS); +} + +static void RunCmdPlay(TestSample &sample) +{ + int32_t ret = sample.adapter->Play(); + if (ret != 0) { + printf("[%s: %d] Play failed ret:%d\n", __func__, __LINE__, ret); + } +} + +static void ShowCmdHelp(void) +{ printf("Input CMD: quit, show, pause(pu), play(pl), seek [ms], volume [lvol] [rvol], loop [bool], speed [float]" - "\n"); - while (fgets(cmd, 20, stdin)) { /* 10: use array length */ - cmd[20] = '\0'; /* 10: end of string */ - if (strncmp(cmd, "quit", 4) == 0) { + "replay, next [cnt], pressure_pupl [cnt], pressure_seek [cnt], sleep [s] cost_test\n"); +} + +static void SampleCmd(TestSample &sample) +{ + char cmd[0x40]; /* 64: Array length */ + int ret; + char *retValue = nullptr; + + ShowCmdHelp(); + while ((retValue = fgets(cmd, 0x20, stdin)) != nullptr) { /* 10: use array length */ + cmd[0x20] = '\0'; /* 10: end of string */ + if (strncmp(cmd, "quit", 0x4) == 0) { + printf("quit\n"); break; - } else if (strncmp(cmd, "pause", 4) == 0 || strncmp(cmd, "pu", 2) == 0) { + } else if (strncmp(cmd, "pause", 0x4) == 0 || strncmp(cmd, "pu", 0x2) == 0) { ret = sample.adapter->Pause(); - } else if (strncmp(cmd, "play", 4) == 0 || strncmp(cmd, "pl", 2) == 0) { - ret = sample.adapter->Play(); - } else if (strncmp(cmd, "speed", 0x5) == 0) { - float speed = 1.0; - if (sscanf_s(cmd, "speed %f", &speed) != 1) { - printf("ERR: not input seek time, example: speed 1.0!\n"); - continue; + } else if (strncmp(cmd, "replay", 0x6) == 0) { + if (ReplayProcess(sample) != 0) { + printf("ReplayProcess process failed\n"); + break; } - ret = sample.adapter->SetPlaybackSpeed(speed); - IS_OK(ret); - } else if (strncmp(cmd, "seek", 4) == 0) { - if (sscanf_s(cmd, "seek %d", &timeMs) != 1) { - printf("ERR: not input seek time, example: seek 1000!\n"); - continue; - } - if (sample.sourceType < 2) { - sample.adapter->Rewind(timeMs, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC); - } - } else if (strncmp(cmd, "volume", 6) == 0) { - if (sscanf_s(cmd, "volume %f %f", &lvolume, &rvolume) != 2) { - printf("ERR: not input volume, example: volume 50 50!\n"); - continue; - } - printf("try set volume %f %f\n", lvolume, rvolume); - ret = sample.adapter->SetVolume(lvolume, rvolume); - } else if (strncmp(cmd, "show", 4) == 0) { - printf("now show player info\n"); - - printf("player IsPlaying:%d IsSingleLooping:%d\n", - sample.adapter->IsPlaying(), sample.adapter->IsSingleLooping()); - - ret = sample.adapter->GetDuration(duration); - IS_OK(ret); - ret = sample.adapter->GetCurrentTime(currentPosition); - IS_OK(ret); - printf("player duration:%lld GetCurrentTime:%ld\n", duration, currentPosition); - - ret = sample.adapter->GetVideoWidth(videoWidth); - IS_OK(ret); - ret = sample.adapter->GetVideoHeight(videoHeight); - IS_OK(ret); - printf("player videoWidth:%d videoHeight:%d\n", videoWidth, videoHeight); - int32_t state; - ret = sample.adapter->GetPlayerState(state); - IS_OK(ret); - printf("player current state:%d\n", state); - } else if (strncmp(cmd, "loop", 4) == 0) { - if (sscanf_s(cmd, "loop %d", &loop) != 1) { - printf("ERR: not input loop flag, example: loop 1!\n"); - continue; - } - printf("try set loop %d\n", loop); - ret = sample.adapter->EnableSingleLooping(loop == 1); - IS_OK(ret); - printf("Set loop %d\n", loop); + } else if (strncmp(cmd, "play", 0x4) == 0 || strncmp(cmd, "pl", 0x2) == 0) { + RunCmdPlay(sample); + } else if (strncmp(cmd, "speed", 0x5) == 0) { + RunCmdSpeed(sample, cmd); + } else if (strncmp(cmd, "seek", 0x4) == 0) { + RunCmdSeek(sample, cmd); + } else if (strncmp(cmd, "volume", 0x6) == 0) { + RunCmdSetVolume(sample, cmd); + } else if (strncmp(cmd, "show", 0x4) == 0) { + RunCmdShow(sample); + } else if (strncmp(cmd, "loop", 0x4) == 0) { + RunCmdLoop(sample, cmd); + } else if (strncmp(cmd, "next", 0x4) == 0) { + RunCmdNext(sample, cmd); + } else if (strncmp(cmd, "pressure_pupl", 0xd) == 0) { + RunCmdPressurePupl(sample, cmd); + } else if (strncmp(cmd, "pressure_seek", 0xd) == 0) { + RunCmdPressureSeek(sample, cmd); + } else if (strncmp(cmd, "sleep", 0x5) == 0) { + RunCmdSleep(cmd); + } else if (strncmp(cmd, "cost_test", 0x9) == 0) { + CostTest(sample); } else { - printf("Input CMD: quit, show, pause(pu), play(pl), seek [ms], volume [lvol] [rvol], loop [bool], " - "speed [float]\n"); + ShowCmdHelp(); } } -} -void SetSchParam(void) -{ - struct sched_param param; - pthread_attr_t attr; - - (void)pthread_attr_getschedparam(&attr, ¶m); - param.sched_priority = 9; - (void)pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); + printf("cmd test end\n"); } -int main(int argc, char** argv) +static int32_t ParseInputParam(int argc, char **argv, TestSample &sample) { - prctl(PR_SET_NAME, "mainProc", 0, 0, 0); int32_t sourceType = 1; int32_t pauseAfterPlay = 0; - SAMPLE_RETURN_VAL_IF_NULL(argv); - if (argc < 2) { /* 2: Minimum number of inputs */ - printf("usage: %s filename (or vpss channel index)\n", argv[0]); + + if (argv == nullptr) { + printf("argv is nullptr error %s %d\n", __FUNCTION__, __LINE__); return -1; } - if (argc >= 3) { /* 4: sourceType */ - sourceType = atoi(argv[2]); /* */ + + if (argc < 0x2) { /* 2: Minimum number of inputs */ + printf("usage: %s filename source_type(1:uri, 2:stream-source) pause-after-play(1:yes, ohter:no)\n", argv[0]); + printf("eg: %s file 1 0\n", argv[0]); + return -1; + } + if (argc >= 0x3) { /* 4: sourceType */ + sourceType = atoi(argv[0x2]); /* */ if ((sourceType != 1) && (sourceType != 0x2)) { printf("unsuport sourceType:%d\n", sourceType); return -1; } } - if (argc >= 4) { - pauseAfterPlay = atoi(argv[2]); + if (argc >= 0x4) { + pauseAfterPlay = atoi(argv[0x3]); if (pauseAfterPlay != 1) { printf("unsuport pauseAfterPlay:%d, not enable pause after play mode\n", sourceType); pauseAfterPlay = 0; } } - TestSample sample = {0}; + pthread_mutex_init(&sample.mutex, nullptr); sample.pauseAfterPlay = pauseAfterPlay; sample.sourceType = sourceType; - if (realpath(argv[1], sample.filePath) == nullptr) { + + if ((sourceType == 0 || sourceType == 0x2) && (realpath(argv[1], sample.filePath) == nullptr)) { printf("realpath input file failed, errno: %d!\n", errno); return -1; + } else if (strlen(argv[1]) < PATH_MAX) { + if (memcpy_s(sample.filePath, PATH_MAX, argv[1], strlen(argv[1]) + 1) != 0) { + printf("memcpy_s failed!\n"); + } + } else { + printf("input path too long!\n"); + return -1; } - sample.adapter = std::make_shared(); - int64_t duration; - int32_t width; - int32_t heighth; - Format formats; - printf("[%s,%d]\n", __func__, __LINE__); - SetSchParam(); - printf("[%s,%d]\n", __func__, __LINE__); printf("[%s,%d] sourceType:%d, path:%s, pauseAfterPlay:%d\n", __func__, __LINE__, sourceType, sample.filePath, pauseAfterPlay); - if (sourceType == 1) { - std::string uri(sample.filePath); - std::map header; - Source source(uri, header); - sample.adapter->SetSource(source); - } else { - struct stat stFileState = {0}; - if (lstat(sample.filePath, &stFileState) != 0) { - printf("lstat %s failed, please check the file exist, errno:%d\n", sample.filePath, errno); - return -1; - } - sample.streamSample = std::make_shared(); - formats.PutStringValue(CODEC_MIME, MIME_AUDIO_AAC); - Source source(sample.streamSample, formats); - sample.adapter->SetSource(source); - pthread_mutex_init(&sample.mutex, nullptr); - sample.isThreadRunning = 1; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 0x10000); - int32_t ret = pthread_create(&sample.process, &attr, streamProcess, &sample); - if (ret != 0) { - printf("pthread_create failed %d\n", ret); - sample.isThreadRunning = 0; - return -1; - } + return 0; +} +int main(int argc, char **argv) +{ + prctl(PR_SET_NAME, "mainProc", 0, 0, 0); + TestSample sample = {0}; + sample.process = -1; + + if (ParseInputParam(argc, argv, sample) != 0) { + return -1; } + GetFileSize(sample); + sample.adapter = std::make_shared(); + SetSourceProcess(sample); + if (sample.pauseAfterPlay != 0) { Format formatSetPauseAfterPlay; formatSetPauseAfterPlay.PutIntValue(PAUSE_AFTER_PLAY, true); @@ -377,44 +834,23 @@ int main(int argc, char** argv) } sample.adapter->Prepare(); - sample.adapter->GetDuration(duration); - printf("[%s,%d] GetDuration:%lld\n", __func__, __LINE__, duration); - sample.adapter->GetVideoWidth(width); - printf("[%s,%d] width:%d\n", __func__, __LINE__, width); - sample.adapter->GetVideoHeight(heighth); - printf("[%s,%d] heighth:%d\n", __func__, __LINE__, heighth); - - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - printf("[%s,%d] CreateSurface failed\n", __func__, __LINE__); - return -1; - } - surface->SetUserData("region_position_x", "0"); - surface->SetUserData("region_position_y", "0"); - surface->SetUserData("region_width", "480"); - surface->SetUserData("region_height", "480"); - sample.adapter->SetVideoSurface(surface); + SetCallback(sample); + SetSurface(sample); + PlayProcess(sample); - if (sample.pauseAfterPlay != 0) { - sample.adapter->Pause(); - } else { - sample.adapter->Play(); - } + sleep(1); - /* ¶¨ÖÆ»¯´¦Àí */ SampleCmd(sample); + EndStreamSourceThread(sample); + int32_t ret = sample.adapter->Stop(); + printf("Stop, ret:%d\n", ret); - sample.adapter->Stop(); - sample.adapter->Reset(); + ret = sample.adapter->Release(); + printf("Release, ret:%d\n", ret); + DestorySurface(sample); + DestoryCallback(sample); + pthread_mutex_destroy(&sample.mutex); - sample.adapter->Release(); - if (sample.sourceType == 2) { - pthread_mutex_lock(&sample.mutex); - sample.isThreadRunning = 0; - pthread_mutex_unlock(&sample.mutex); - pthread_join(sample.process, nullptr); - pthread_mutex_destroy(&sample.mutex); - } printf("[%s, %d] main end\n", __func__, __LINE__); return 0; }