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 = ∈
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