• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 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 
16 #include <stdio.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <pthread.h>
22 #include <sys/select.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <sys/prctl.h>
28 #include "source.h"
29 #include "player.h"
30 #include "format.h"
31 #include <string>
32 #include <sys/prctl.h>
33 #include "securec.h"
34 
35 using OHOS::Surface;
36 
37 using OHOS::Media::Player;
38 using OHOS::Media::PlayerSeekMode;
39 using OHOS::Media::Source;
40 using OHOS::Media::Format;
41 using OHOS::Media::StreamSource;
42 using OHOS::Media::StreamCallback;
43 using namespace OHOS::Media;
44 
GetCurTimeUs()45 static int64_t GetCurTimeUs()
46 {
47     const int32_t  SS2US = 1000000;
48     struct timeval ts;
49     ts.tv_sec = 0;
50     ts.tv_usec = 0;
51     gettimeofday(&ts, nullptr);
52     return (static_cast<int64_t> (ts.tv_sec) * SS2US) + static_cast<int64_t> (ts.tv_usec);
53 }
54 
GetCurTimeMs()55 static int64_t GetCurTimeMs()
56 {
57     const int32_t US2MS = 1000;
58     int64_t curTimeUs = GetCurTimeUs();
59     return static_cast<int64_t>(curTimeUs / US2MS);
60 }
61 
62 class StreamSourceSample;
63 struct TestSample {
64     std::shared_ptr<Player> adapter;
65     pthread_t process;
66     pthread_mutex_t mutex;
67     bool isThreadRunning;
68     int32_t sourceType;
69     char filePath[PATH_MAX + 1];
70     int64_t fileSize;
71     int32_t pauseAfterPlay;
72     Surface *surface;
73     std::shared_ptr<StreamSourceSample> streamSample;
74     std::shared_ptr<PlayerCallback> cb;
75     int64_t newPlayerCost;
76     int64_t setSourceCost;
77     int64_t prepareCost;
78     int64_t setSurfaceCost;
79     int64_t playCost;
80     int64_t RewindCost;
81     int64_t RewindBegin;
82     int64_t stopCost;
83     int64_t releaseCost;
84 };
85 
86 struct IdleBuffer {
87     size_t idx;
88     size_t offset;
89     size_t size;
90 };
91 
92 class StreamSourceSample : public StreamSource {
93 public:
94     StreamSourceSample(void);
95     virtual ~StreamSourceSample(void);
96     void OnBufferAvailable(size_t index, size_t offset, size_t size);
97     void SetStreamCallback(const std::shared_ptr<StreamCallback> &callback);
98     uint8_t *GetBufferAddress(size_t idx);
99     void QueueBuffer(size_t index, size_t offset, size_t size, int64_t timestampUs, uint32_t flags);
100     int GetAvailableBuffer(IdleBuffer *buffer);
101 
102 private:
103     std::weak_ptr<StreamCallback> m_callBack;
104     std::vector<IdleBuffer> aviableBuffer;
105     pthread_mutex_t m_mutex;
106 };
107 
StreamSourceSample(void)108 StreamSourceSample::StreamSourceSample(void)
109 {
110     aviableBuffer.clear();
111     pthread_mutex_init(&m_mutex, nullptr);
112 }
113 
~StreamSourceSample(void)114 StreamSourceSample::~StreamSourceSample(void)
115 {
116     aviableBuffer.clear();
117     pthread_mutex_destroy(&m_mutex);
118 }
119 
SetStreamCallback(const std::shared_ptr<StreamCallback> & callback)120 void StreamSourceSample::SetStreamCallback(const std::shared_ptr<StreamCallback> &callback)
121 {
122     m_callBack = callback;
123 }
124 
GetBufferAddress(size_t idx)125 uint8_t *StreamSourceSample::GetBufferAddress(size_t idx)
126 {
127     std::shared_ptr<StreamCallback> callback = m_callBack.lock();
128     if (callback == nullptr) {
129         return nullptr;
130     }
131     return callback->GetBuffer(idx);
132 }
133 
QueueBuffer(size_t index,size_t offset,size_t size,int64_t timestampUs,uint32_t flags)134 void StreamSourceSample::QueueBuffer(size_t index, size_t offset, size_t size, int64_t timestampUs, uint32_t flags)
135 {
136     std::shared_ptr<StreamCallback> callback = m_callBack.lock();
137     if (callback == nullptr) {
138         return;
139     }
140     callback->QueueBuffer(index, offset, size, timestampUs, flags);
141 }
142 
OnBufferAvailable(size_t index,size_t offset,size_t size)143 void StreamSourceSample::OnBufferAvailable(size_t index, size_t offset, size_t size)
144 {
145     IdleBuffer buffer;
146     pthread_mutex_lock(&m_mutex);
147     buffer.idx = index;
148     buffer.offset = offset;
149     buffer.size = size;
150     aviableBuffer.push_back(buffer);
151     pthread_mutex_unlock(&m_mutex);
152 }
153 
GetAvailableBuffer(IdleBuffer * buffer)154 int StreamSourceSample::GetAvailableBuffer(IdleBuffer* buffer)
155 {
156     if (buffer == nullptr) {
157         printf("buffer is nullptr error %s %d\n", __FUNCTION__, __LINE__);
158         return -1;
159     }
160     pthread_mutex_lock(&m_mutex);
161     if (aviableBuffer.empty()) {
162         pthread_mutex_unlock(&m_mutex);
163         return -1;
164     }
165     *buffer = aviableBuffer[0];
166     aviableBuffer.erase(aviableBuffer.begin());
167     pthread_mutex_unlock(&m_mutex);
168     return 0;
169 }
170 
171 class PlayerCallbackImpl : public PlayerCallback {
172 public:
173     PlayerCallbackImpl(TestSample &in);
174     ~PlayerCallbackImpl();
175     void OnPlaybackComplete();
176     void OnError(int32_t errorType, int32_t errorCode);
177     void OnInfo(int type, int extra);
178     void OnVideoSizeChanged(int width, int height);
179     void OnRewindToComplete();
180 
181 private:
182     TestSample *sample;
183 };
184 
PlayerCallbackImpl(TestSample & in)185 PlayerCallbackImpl::PlayerCallbackImpl(TestSample &in)
186 {
187     sample = &in;
188 }
189 
~PlayerCallbackImpl()190 PlayerCallbackImpl::~PlayerCallbackImpl()
191 {
192     printf("dtor\n");
193 }
194 
OnPlaybackComplete(void)195 void PlayerCallbackImpl::OnPlaybackComplete(void)
196 {
197     printf("OnPlaybackComplete test\n");
198 }
199 
OnError(int32_t errorType,int32_t errorCode)200 void PlayerCallbackImpl::OnError(int32_t errorType, int32_t errorCode)
201 {
202     printf("OnError test, errorType:%d, errorCode:%d\n", errorType, errorCode);
203 }
204 
OnInfo(int type,int extra)205 void PlayerCallbackImpl::OnInfo(int type, int extra)
206 {
207     printf("OnInfo test, type:%d, extra:%d\n", type, extra);
208 }
209 
OnVideoSizeChanged(int width,int height)210 void PlayerCallbackImpl::OnVideoSizeChanged(int width, int height)
211 {
212     printf("OnVideoSizeChanged test width:%d, height:%d\n", width, height);
213 }
214 
OnRewindToComplete(void)215 void PlayerCallbackImpl::OnRewindToComplete(void)
216 {
217     sample->RewindCost = GetCurTimeMs() - sample->RewindBegin;
218     printf("OnRewindToComplete test\n");
219 }
220 
CostTestPrintf(TestSample & sample)221 static void CostTestPrintf(TestSample &sample)
222 {
223     printf("\n\n\n##################player cost info begin\n");
224 
225     printf("start cost total:%lld\n", sample.setSourceCost + sample.prepareCost + sample.setSurfaceCost +
226         sample.playCost);
227     printf("new player:%lld,\n setSourceCost:%lld,\n prepareCost:%lld,\n, setSurfaceCost:%lld,\n playCost:%lld,\n",
228         sample.newPlayerCost, sample.setSourceCost, sample.prepareCost, sample.setSurfaceCost, sample.playCost);
229 
230     printf("seek cost total:%lld\n", sample.RewindCost);
231 
232     printf("destory cost total:%lld\n", sample.stopCost + sample.releaseCost);
233     printf("stopCost:%lld,\n releaseCost:%lld,\n", sample.stopCost, sample.releaseCost);
234 
235     printf("##################player cost info end\n\n\n");
236 }
237 
238 #ifdef ENABLE_PASSTHROUGH_SAMPLE
streamProcess(void * arg)239 static void *streamProcess(void *arg)
240 {
241 printf("####### streamProcess in \n");
242     const int32_t READ_LEN = 1024;
243     const int32_t STEAM_PROCESS_SLEEP_TIME_US = 5000;
244     IdleBuffer buffer;
245     uint8_t *data = nullptr;
246     size_t readLen;
247     size_t len;
248     TestSample *sample = (TestSample *)arg;
249     char resolvedPath[PATH_MAX] = { 0 };
250     if (realpath(sample->filePath, resolvedPath) == nullptr) {
251         printf("realpath file error \n");
252         return nullptr;
253     }
254 
255     FILE* pFile = fopen(resolvedPath, "rb");
256     if (pFile == nullptr) {
257         return nullptr;
258     }
259     prctl(PR_SET_NAME, "StreamProc", 0, 0, 0);
260     while (true) {
261         if (!sample->isThreadRunning) {
262             break;
263         }
264 
265         if (sample->streamSample->GetAvailableBuffer(&buffer) != 0) {
266             usleep(STEAM_PROCESS_SLEEP_TIME_US);
267             continue;
268         }
269         data = sample->streamSample->GetBufferAddress(buffer.idx);
270         if (data == nullptr) {
271             printf("[%s, %d] get buffer null", __func__, __LINE__);
272             break;
273         }
274         len = (buffer.size < READ_LEN) ? buffer.size : READ_LEN;
275         readLen = fread(data + buffer.offset, 1, len, pFile);
276         if (readLen <= len && readLen > 0) {
277             sample->streamSample->QueueBuffer(buffer.idx, buffer.offset, readLen, 0, 0x8);
278         } else {
279             sample->streamSample->QueueBuffer(buffer.idx, buffer.offset, readLen, 0, 0x4);
280             printf("[%s, %d] have render eos", __func__, __LINE__);
281             break;
282         }
283     }
284     fclose(pFile);
285     printf("[%s,%d]\n", __func__, __LINE__);
286     sample->isThreadRunning = false;
287     return nullptr;
288 }
289 #else
streamProcess(void * arg)290 static void *streamProcess(void *arg)
291 {
292     const int32_t STEAM_PROCESS_SLEEP_TIME_US = 20000;
293     uint8_t *data = nullptr;
294     size_t readLen;
295     size_t bufferSize;
296     TestSample *sample = (TestSample *)arg;
297     FILE* pFile = fopen(sample->filePath, "rb");
298     if (pFile == nullptr) {
299         return nullptr;
300     }
301     prctl(PR_SET_NAME, "StreamProc", 0, 0, 0);
302     printf("[%s,%d] file:%s\n", __func__, __LINE__, sample->filePath);
303     while (true) {
304         pthread_mutex_lock(&sample->mutex);
305         if (!sample->isThreadRunning) {
306             printf("[%s,%d] thread should exit\n", __func__, __LINE__);
307             pthread_mutex_unlock(&sample->mutex);
308             break;
309         }
310         pthread_mutex_unlock(&sample->mutex);
311         data = sample->streamSample->GetSharedBuffer(bufferSize);
312         if (data == nullptr) {
313             usleep(STEAM_PROCESS_SLEEP_TIME_US);
314             continue;
315         }
316         readLen = fread(data, 1, bufferSize, pFile);
317         if (readLen > 0) {
318             sample->streamSample->QueueSharedBuffer(data, readLen);
319         } else {
320             sample->streamSample->QueueSharedBuffer(data, 0);
321             break;
322         }
323     }
324     fclose(pFile);
325     printf("[%s,%d]\n", __func__, __LINE__);
326     pthread_mutex_lock(&sample->mutex);
327     sample->isThreadRunning = false;
328     pthread_mutex_unlock(&sample->mutex);
329     return nullptr;
330 }
331 #endif
GetFileSize(TestSample & sample)332 static void GetFileSize(TestSample &sample)
333 {
334     sample.fileSize = -1;
335     if (sample.sourceType != 1 && sample.sourceType != 0) {
336         return;
337     }
338 
339     FILE *fileTmp = fopen(sample.filePath, "rb");
340     if (fileTmp != nullptr) {
341         fseek(fileTmp, 0, SEEK_END);
342         sample.fileSize = ftell(fileTmp);
343         fclose(fileTmp);
344         fileTmp = nullptr;
345     }
346 }
347 
SetSurface(TestSample & sample)348 static int SetSurface(TestSample &sample)
349 {
350     if (sample.surface != nullptr) {
351         return 0;
352     }
353 
354     int64_t begin = GetCurTimeMs();
355 
356     sample.surface = Surface::CreateSurface();
357     if (sample.surface == nullptr) {
358         printf("[%s,%d] CreateSurface failed\n",  __func__, __LINE__);
359         return -1;
360     }
361     sample.surface->SetUserData("region_position_x", "0");
362     sample.surface->SetUserData("region_position_y", "0");
363     sample.surface->SetUserData("region_width", "480");
364     sample.surface->SetUserData("region_height", "480");
365     int32_t ret = sample.adapter->SetVideoSurface(sample.surface);
366     sample.setSurfaceCost = GetCurTimeMs() - begin;
367     if (ret != 0) {
368         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
369     }
370     return 0;
371 }
372 
DestorySurface(TestSample & sample)373 static void DestorySurface(TestSample &sample)
374 {
375     if (sample.surface != nullptr) {
376         delete(sample.surface);
377         sample.surface = nullptr;
378     }
379 }
380 
SetCallback(TestSample & sample)381 static int SetCallback(TestSample &sample)
382 {
383     if (sample.cb == nullptr) {
384         sample.cb = std::make_shared<PlayerCallbackImpl>(sample);
385         sample.adapter->SetPlayerCallback(sample.cb);
386     }
387     return 0;
388 }
389 
DestoryCallback(TestSample & sample)390 static void DestoryCallback(TestSample &sample)
391 {
392     if (sample.cb != nullptr) {
393         sample.cb.reset();
394         sample.cb = nullptr;
395     }
396 }
397 
SetStreamSourceProcess(TestSample & sample)398 static int SetStreamSourceProcess(TestSample &sample)
399 {
400     sample.streamSample = std::make_shared<StreamSourceSample>();
401     Format formats;
402     formats.PutStringValue(CODEC_MIME, MIME_AUDIO_AAC);
403     Source source(sample.streamSample, formats);
404     sample.adapter->SetSource(source);
405     sample.isThreadRunning = true;
406     pthread_attr_t attr;
407     pthread_attr_init(&attr);
408     pthread_attr_setstacksize(&attr, 0x10000);
409     int32_t ret = pthread_create(&sample.process, &attr, streamProcess, &sample);
410     if (ret != 0) {
411         printf("pthread_create failed %d\n", ret);
412         sample.isThreadRunning = false;
413         return -1;
414     }
415     return 0;
416 }
417 
SetSourceProcess(TestSample & sample)418 static int SetSourceProcess(TestSample &sample)
419 {
420     int64_t begin = GetCurTimeMs();
421     if (sample.sourceType == 1) {
422         std::string uri(sample.filePath);
423         std::map<std::string, std::string> header;
424         Source source(uri, header);
425         sample.adapter->SetSource(source);
426     } else {
427         struct stat stFileState = {0};
428         if (lstat(sample.filePath, &stFileState) != 0) {
429             printf("lstat %s failed, please check the file exist, errno:%d\n", sample.filePath, errno);
430             return -1;
431         }
432         if (SetStreamSourceProcess(sample) != 0) {
433             printf("SetStreamSourceProcess failed\n");
434             return -1;
435         }
436     }
437     sample.setSourceCost = GetCurTimeMs() - begin;
438     return 0;
439 }
440 
PrepareProcess(TestSample & sample)441 static int PrepareProcess(TestSample &sample)
442 {
443     int64_t begin = GetCurTimeMs();
444 
445     if (sample.pauseAfterPlay != 0) {
446         Format formatSetPauseAfterPlay;
447         formatSetPauseAfterPlay.PutIntValue(PAUSE_AFTER_PLAY, true);
448         sample.adapter->SetParameter(formatSetPauseAfterPlay);
449     }
450     sample.adapter->Prepare();
451     sample.prepareCost = GetCurTimeMs() - begin;
452 
453     SetCallback(sample);
454     SetSurface(sample);
455     return 0;
456 }
457 
PlayProcess(TestSample & sample)458 static int PlayProcess(TestSample &sample)
459 {
460     int32_t ret;
461     int64_t begin = GetCurTimeMs();
462 
463     if (sample.pauseAfterPlay != 0) {
464         ret = sample.adapter->Pause();
465     } else {
466         ret = sample.adapter->Play();
467     }
468     sample.playCost = GetCurTimeMs() - begin;
469     if (ret != 0) {
470         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
471     }
472     return 0;
473 }
474 
ReleaseProcess(TestSample & sample)475 static int ReleaseProcess(TestSample &sample)
476 {
477     int32_t ret;
478     int64_t begin = GetCurTimeMs();
479 
480     if (sample.pauseAfterPlay != 0) {
481         ret = sample.adapter->Pause();
482     } else {
483         ret = sample.adapter->Play();
484     }
485     sample.playCost = GetCurTimeMs() - begin;
486     if (ret != 0) {
487         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
488     }
489     return 0;
490 }
491 
EndStreamSourceThread(TestSample & sample)492 static void EndStreamSourceThread(TestSample &sample)
493 {
494     if (sample.sourceType == 0x2 && sample.process != -1) {
495         pthread_mutex_lock(&sample.mutex);
496         sample.isThreadRunning = false;
497         pthread_mutex_unlock(&sample.mutex);
498         pthread_join(sample.process, nullptr);
499         sample.process = -1;
500     }
501 }
502 
CreatePlayerProcess(TestSample & sample)503 static int CreatePlayerProcess(TestSample &sample)
504 {
505     SetSourceProcess(sample);
506     PrepareProcess(sample);
507     PlayProcess(sample);
508     return 0;
509 }
510 
ReplayProcess(TestSample & sample)511 static int ReplayProcess(TestSample &sample)
512 {
513     EndStreamSourceThread(sample);
514     sample.adapter->Stop();
515 
516     sample.adapter->Release();
517     sample.adapter.reset();
518 
519     DestorySurface(sample);
520     DestoryCallback(sample);
521     if (sample.sourceType == 0x2) {
522         sample.streamSample.reset();
523     }
524 
525     sample.adapter = std::make_shared<Player>();
526 
527     return CreatePlayerProcess(sample);
528 }
529 
PlayNextProcess(TestSample & sample)530 static int PlayNextProcess(TestSample &sample)
531 {
532     EndStreamSourceThread(sample);
533     sample.adapter->Stop();
534     sample.adapter->Reset();
535     DestorySurface(sample);
536     if (sample.sourceType == 0x2) {
537         sample.streamSample.reset();
538     }
539 
540     return CreatePlayerProcess(sample);
541 }
542 
CostTest(TestSample & sample)543 static int CostTest(TestSample &sample)
544 {
545     if (sample.sourceType >= 0x2) {
546         return 0;
547     }
548 
549     int64_t begin;
550     int64_t end;
551 
552     EndStreamSourceThread(sample);
553     begin = GetCurTimeMs();
554     sample.adapter->Stop();
555     end = GetCurTimeMs();
556     sample.stopCost = end - begin;
557 
558     begin = end;
559     sample.adapter->Release();
560     sample.adapter.reset();
561     sample.releaseCost = GetCurTimeMs() - begin;
562 
563     DestorySurface(sample);
564     DestoryCallback(sample);
565     if (sample.sourceType == 0x2) {
566         sample.streamSample.reset();
567     }
568     CostTestPrintf(sample);
569 
570     begin = GetCurTimeMs();
571     sample.adapter = std::make_shared<Player>();
572     sample.newPlayerCost = GetCurTimeMs() - begin;
573 
574     CreatePlayerProcess(sample);
575 
576     sleep(0xa); // sleep 10s and seek
577     sample.RewindBegin = GetCurTimeMs();
578     sample.adapter->Rewind(0, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC);
579     sleep(0x5); // sleep 5s after seek
580     return 0;
581 }
582 
RunCmdShow(TestSample & sample)583 static void RunCmdShow(TestSample &sample)
584 {
585     printf("now show player info\n");
586 
587     printf("player IsPlaying:%d IsSingleLooping:%d\n", sample.adapter->IsPlaying(),
588         sample.adapter->IsSingleLooping());
589 
590     int64_t duration;
591     int32_t ret = sample.adapter->GetDuration(duration);
592     if (ret != 0) {
593         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
594     }
595 
596     int64_t currentPosition;
597     ret = sample.adapter->GetCurrentTime(currentPosition);
598     if (ret != 0) {
599         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
600     }
601     printf("player duration:%lld GetCurrentTime:%lld\n", duration, currentPosition);
602 
603     int32_t videoWidth;
604     int32_t videoHeight;
605     ret = sample.adapter->GetVideoWidth(videoWidth);
606     if (ret != 0) {
607         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
608     }
609     ret = sample.adapter->GetVideoHeight(videoHeight);
610     if (ret != 0) {
611         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
612     }
613     printf("player videoWidth:%d videoHeight:%d\n", videoWidth, videoHeight);
614     int32_t state;
615     ret = sample.adapter->GetPlayerState(state);
616     if (ret != 0) {
617         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
618     }
619     printf("player current state:%d\n", state);
620 }
621 
RunCmdSetVolume(TestSample & sample,const char cmd[])622 static void RunCmdSetVolume(TestSample &sample, const char cmd[])
623 {
624     float lvolume;
625     float rvolume;
626 
627     if (sscanf_s(cmd, "setvolume %f %f", &lvolume, &rvolume) != 0x2) {
628         printf("ERR: not input volume, example: volume 50 50!\n");
629         return;
630     }
631     printf("try set volume %f %f\n", lvolume, rvolume);
632     int32_t ret = sample.adapter->SetVolume(lvolume, rvolume);
633     if (ret != 0) {
634         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
635     }
636 }
637 
RunCmdNext(TestSample & sample,const char cmd[])638 static void RunCmdNext(TestSample &sample, const char cmd[])
639 {
640     int32_t cnt;
641 
642     if (sscanf_s(cmd, "next %d", &cnt) != 1) {
643         printf("ERR: not input next play count, example: next 10000!\n");
644         return;
645     }
646 
647     while (cnt > 0) {
648         if (PlayNextProcess(sample) != 0) {
649             printf("PlayNextProcess process failed\n");
650             return;
651         }
652         sleep(0x5); // sleep 5s and loop
653         cnt--;
654     };
655 }
656 
RunCmdPressurePupl(TestSample & sample,const char cmd[])657 static void RunCmdPressurePupl(TestSample &sample, const char cmd[])
658 {
659     int32_t cnt;
660     int ret;
661 
662     if (sscanf_s(cmd, "pressure_pupl %d", &cnt) != 1) {
663         printf("ERR: not input replay count, example: pressure 10000!\n");
664         return;
665     }
666     while (cnt > 0) {
667         ret = sample.adapter->Pause();
668         sleep(1);
669         ret = sample.adapter->Play();
670         sleep(1);
671         cnt--;
672     }
673 }
674 
RunCmdPressureSeek(TestSample & sample,const char cmd[])675 static void RunCmdPressureSeek(TestSample &sample, const char cmd[])
676 {
677     int32_t cnt;
678     int ret;
679 
680     if (sscanf_s(cmd, "pressure_seek %d", &cnt) != 1) {
681         printf("ERR: not input replay count, example: pressure 10000!\n");
682         return;
683     }
684     if (sample.sourceType == 0x2) {
685         printf("ERR: streamsource not support pressure_seek\n");
686         return;
687     }
688 
689     const int32_t rewindPos = 5000;
690     int64_t currentPosition;
691     while (cnt > 0) {
692         sample.adapter->Rewind(rewindPos, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC);
693         ret = sample.adapter->GetCurrentTime(currentPosition);
694         printf("##############player GetCurrentTime, ret:%d, time:%lld\n", ret, currentPosition);
695         sleep(0x2);
696         cnt--;
697     }
698 }
699 
RunCmdLoop(TestSample & sample,const char cmd[])700 static void RunCmdLoop(TestSample &sample, const char cmd[])
701 {
702     int32_t loop;
703 
704     if (sscanf_s(cmd, "loop %d", &loop) != 1) {
705         printf("ERR: not input loop flag, example: loop 1!\n");
706         return;
707     }
708 
709     printf("try set loop %d\n", loop);
710     int32_t ret = sample.adapter->EnableSingleLooping(loop == 1);
711     if (ret != 0) {
712         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
713     }
714     printf("Set loop %d\n", loop);
715 }
716 
RunCmdSpeed(TestSample & sample,const char cmd[])717 static void RunCmdSpeed(TestSample &sample, const char cmd[])
718 {
719     float speed = 1.0;
720     if (sscanf_s(cmd, "speed %f", &speed) != 1) {
721         printf("ERR: not input seek time, example: speed 1.0!\n");
722         return;
723     }
724 
725     int32_t ret = sample.adapter->SetPlaybackSpeed(speed);
726     if (ret != 0) {
727         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
728     }
729 }
730 
RunCmdSeek(TestSample & sample,const char cmd[])731 static void RunCmdSeek(TestSample &sample, const char cmd[])
732 {
733     int64_t timeMs = 0;
734     if (sscanf_s(cmd, "seek %d", &timeMs) != 1) {
735         printf("ERR: not input seek time, example: seek 1000!\n");
736         return;
737     }
738 
739     int32_t ret = sample.adapter->Rewind(timeMs, PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC);
740     if (ret != 0) {
741         printf("[%s: %d] ret:%d\n", __func__, __LINE__, ret);
742     }
743 }
744 
RunCmdSleep(const char cmd[])745 static void RunCmdSleep(const char cmd[])
746 {
747     int64_t timeS = 0;
748     if (sscanf_s(cmd, "sleep %d", &timeS) != 1) {
749         printf("ERR: not input replay count, example: sleep 100!\n");
750         return;
751     }
752     sleep(timeS);
753 }
754 
RunCmdPlay(TestSample & sample)755 static void RunCmdPlay(TestSample &sample)
756 {
757     int32_t ret = sample.adapter->Play();
758     if (ret != 0) {
759         printf("[%s: %d] Play failed ret:%d\n", __func__, __LINE__, ret);
760     }
761 }
762 
ShowCmdHelp(void)763 static void ShowCmdHelp(void)
764 {
765     printf("Input CMD: quit, show, pause(pu), play(pl), seek [ms], volume [lvol] [rvol], loop [bool], speed [float]"
766         "replay, next [cnt], pressure_pupl [cnt], pressure_seek [cnt], sleep [s] cost_test\n");
767 }
768 
SampleCmd(TestSample & sample)769 static void SampleCmd(TestSample &sample)
770 {
771     char cmd[0x40];   /* 64: Array length */
772     int ret;
773     char *retValue = nullptr;
774 
775     ShowCmdHelp();
776     while ((retValue = fgets(cmd, 0x20, stdin)) != nullptr) {  /* 10: use array length */
777         cmd[0x20] = '\0';  /* 10: end of string */
778         if (strncmp(cmd, "quit", 0x4) == 0) {
779             printf("quit\n");
780             break;
781         } else if (strncmp(cmd, "pause", 0x4) == 0 || strncmp(cmd, "pu", 0x2) == 0) {
782             ret = sample.adapter->Pause();
783         } else if (strncmp(cmd, "replay", 0x6) == 0) {
784             if (ReplayProcess(sample) != 0) {
785                 printf("ReplayProcess process failed\n");
786                 break;
787             }
788         } else if (strncmp(cmd, "play", 0x4) == 0 || strncmp(cmd, "pl", 0x2) == 0) {
789             RunCmdPlay(sample);
790         } else if (strncmp(cmd, "speed", 0x5) == 0) {
791             RunCmdSpeed(sample, cmd);
792         } else if (strncmp(cmd, "seek", 0x4) == 0) {
793             RunCmdSeek(sample, cmd);
794         } else if (strncmp(cmd, "volume", 0x6) == 0) {
795             RunCmdSetVolume(sample, cmd);
796         } else if (strncmp(cmd, "show", 0x4) == 0) {
797             RunCmdShow(sample);
798         } else if (strncmp(cmd, "loop", 0x4) == 0) {
799             RunCmdLoop(sample, cmd);
800         } else if (strncmp(cmd, "next", 0x4) == 0) {
801             RunCmdNext(sample, cmd);
802         } else if (strncmp(cmd, "pressure_pupl", 0xd) == 0) {
803             RunCmdPressurePupl(sample, cmd);
804         } else if (strncmp(cmd, "pressure_seek", 0xd) == 0) {
805             RunCmdPressureSeek(sample, cmd);
806         } else if (strncmp(cmd, "sleep", 0x5) == 0) {
807             RunCmdSleep(cmd);
808         } else if (strncmp(cmd, "cost_test", 0x9) == 0) {
809             CostTest(sample);
810         } else {
811             ShowCmdHelp();
812         }
813     }
814 
815     printf("cmd test end\n");
816 }
817 
ParseInputParam(int argc,char ** argv,TestSample & sample)818 static int32_t ParseInputParam(int argc, char **argv, TestSample &sample)
819 {
820     int32_t sourceType = 1;
821     int32_t pauseAfterPlay = 0;
822 
823     if (argv == nullptr) {
824         printf("argv is nullptr error %s %d\n", __FUNCTION__, __LINE__);
825         return -1;
826     }
827 
828     if (argc < 0x2) {  /* 2: Minimum number of inputs */
829         printf("usage: %s filename source_type(1:uri, 2:stream-source) pause-after-play(1:yes, ohter:no)\n", argv[0]);
830         printf("eg: %s file 1 0\n", argv[0]);
831         return -1;
832     }
833     if (argc >= 0x3) {  /* 4:  sourceType */
834         sourceType = atoi(argv[0x2]);  /*  */
835         if ((sourceType != 1) && (sourceType != 0x2)) {
836             printf("unsuport sourceType:%d\n", sourceType);
837             return -1;
838         }
839     }
840     if (argc >= 0x4) {
841         pauseAfterPlay = atoi(argv[0x3]);
842         if (pauseAfterPlay != 1) {
843             printf("unsuport pauseAfterPlay:%d, not enable pause after play mode\n", sourceType);
844             pauseAfterPlay = 0;
845         }
846     }
847 
848     pthread_mutex_init(&sample.mutex, nullptr);
849     sample.pauseAfterPlay = pauseAfterPlay;
850     sample.sourceType = sourceType;
851 
852     if ((sourceType == 0 || sourceType == 0x2) && (realpath(argv[1], sample.filePath) == nullptr)) {
853         printf("realpath input file failed, errno: %d!\n", errno);
854         return -1;
855     } else if (strlen(argv[1]) < PATH_MAX) {
856         if (memcpy_s(sample.filePath, PATH_MAX, argv[1], strlen(argv[1]) + 1) != 0) {
857             printf("memcpy_s failed!\n");
858         }
859     } else {
860         printf("input path too long!\n");
861         return -1;
862     }
863 
864     printf("[%s,%d] sourceType:%d, path:%s, pauseAfterPlay:%d\n", __func__, __LINE__, sourceType, sample.filePath,
865         pauseAfterPlay);
866     return 0;
867 }
main(int argc,char ** argv)868 int main(int argc, char **argv)
869 {
870     prctl(PR_SET_NAME, "mainProc", 0, 0, 0);
871     TestSample sample = {0};
872     sample.process = -1;
873 
874     if (ParseInputParam(argc, argv, sample) != 0) {
875         return -1;
876     }
877 
878     GetFileSize(sample);
879     sample.adapter = std::make_shared<Player>();
880     SetSourceProcess(sample);
881 
882     if (sample.pauseAfterPlay != 0) {
883         Format formatSetPauseAfterPlay;
884         formatSetPauseAfterPlay.PutIntValue(PAUSE_AFTER_PLAY, true);
885         sample.adapter->SetParameter(formatSetPauseAfterPlay);
886     }
887     sample.adapter->Prepare();
888 
889     SetCallback(sample);
890     SetSurface(sample);
891     PlayProcess(sample);
892 
893     sleep(1);
894 
895     SampleCmd(sample);
896     EndStreamSourceThread(sample);
897     int32_t ret = sample.adapter->Stop();
898     printf("Stop, ret:%d\n", ret);
899 
900     ret = sample.adapter->Release();
901     printf("Release, ret:%d\n", ret);
902     DestorySurface(sample);
903     DestoryCallback(sample);
904     pthread_mutex_destroy(&sample.mutex);
905 
906     printf("[%s, %d] main end\n", __func__, __LINE__);
907     return 0;
908 }
909