2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef __PLUSPLAYER_UT_INCLUDE_ES_EVENT_LISTENER_H__
18 #define __PLUSPLAYER_UT_INCLUDE_ES_EVENT_LISTENER_H__
24 #include <condition_variable>
26 #include "esplusplayer_capi/esplusplayer_capi.h"
27 #include "ut/include/esplusplayer/esreader.hpp"
29 class EsPlayerEventCallback {
31 EsPlayerEventCallback(esplusplayer_handle handle,
32 EsStreamReader* video_reader,
33 EsStreamReader* audio_reader)
35 video_reader_(video_reader),
36 audio_reader_(audio_reader) {}
37 ~EsPlayerEventCallback() {
38 if (audio_feeding_task_.joinable()) audio_feeding_task_.join();
39 if (video_feeding_task_.joinable()) video_feeding_task_.join();
41 void SetCallback(void) {
42 esplusplayer_set_error_cb(handle_, OnError, this);
43 esplusplayer_set_buffer_status_cb(handle_, OnBufferStatus, this);
44 esplusplayer_set_buffer_byte_status_cb(handle_, OnBufferByteStatus, this);
45 esplusplayer_set_buffer_time_status_cb(handle_, OnBufferTimeStatus, this);
46 esplusplayer_set_resource_conflicted_cb(handle_, OnResourceConflicted,
48 esplusplayer_set_eos_cb(handle_, OnEos, this);
49 esplusplayer_set_ready_to_prepare_cb(handle_, OnReadyToPrepare, this);
50 esplusplayer_set_prepare_async_done_cb(handle_, OnPrepareDone, this);
51 esplusplayer_set_seek_done_cb(handle_, OnSeekDone, this);
52 esplusplayer_set_ready_to_seek_cb(handle_, OnReadyToSeek, this);
53 esplusplayer_set_media_packet_video_decoded_cb(handle_, OnVideoDecoded,
55 esplusplayer_set_closed_caption_cb(handle_, OnClosedCaption, this);
56 esplusplayer_set_flush_done_cb(handle_, OnFlushDone, this);
57 esplusplayer_set_event_cb(handle_, OnEvent, this);
60 static void DataFeedingTask(EsStreamReader* stream,
61 esplusplayer_handle esplayer) {
62 esplusplayer_es_packet pkt;
64 memset(&pkt, 0, sizeof(esplusplayer_es_packet));
65 if (!stream->ReadNextPacket(pkt)) break;
66 esplusplayer_submit_packet(esplayer, &pkt);
70 static void OnError(const esplusplayer_error_type err_code, void* userdata) {
71 std::cout << "OnError : " << esplusplayer_get_error_string(err_code) << std::endl;
73 static void OnResourceConflicted(void* userdata) {
74 std::cout << "OnResourceConflicted" << std::endl;
76 static void OnSeekDone(void* userdata) {
77 std::cout << "OnSeekDone" << std::endl;
79 static void OnBufferByteStatus(const esplusplayer_stream_type,
80 const esplusplayer_buffer_status, uint64_t,
82 // std::cout << "OnBufferByteStatus" << std::endl;
84 static void OnBufferTimeStatus(const esplusplayer_stream_type,
85 const esplusplayer_buffer_status, uint64_t,
87 // std::cout << "OnBufferTimeStatus" << std::endl;
89 static void OnVideoDecoded(const esplusplayer_decoded_video_packet * pkt,
91 EsPlayerEventCallback* cb = static_cast<EsPlayerEventCallback*>(userdata);
93 std::cout << "OnVideoDecoded" << std::endl;
94 esplusplayer_decoded_buffer_destroy (cb->handle_, (esplusplayer_decoded_video_packet *)pkt);
96 static void OnClosedCaption(const char* data, const int size,
98 std::cout << "OnClosedCaption" << std::endl;
100 static void OnFlushDone(void* userdata) {
101 std::cout << "OnFlushDone" << std::endl;
103 static void OnEvent(const esplusplayer_event_type,
104 const esplusplayer_event_msg, void*) {
105 std::cout << "OnEvent" << std::endl;
107 static void OnEos(void* userdata) {
108 EsPlayerEventCallback* cb = static_cast<EsPlayerEventCallback*>(userdata);
109 std::unique_lock<std::mutex> lk(cb->eos_m_);
110 std::cout << "OnEos" << std::endl;
113 cb->eos_cv_.notify_all();
115 static void OnPrepareDone(bool ret, void* userdata) {
116 EsPlayerEventCallback* cb = static_cast<EsPlayerEventCallback*>(userdata);
117 std::unique_lock<std::mutex> lk(cb->prepare_done_m_);
118 std::cout << "OnPrepareDone" << std::endl;
119 cb->prepare_done_ = true;
120 cb->prepare_done_result_ = ret;
122 cb->prepare_done_cv_.notify_all();
124 static void OnBufferStatus(const esplusplayer_stream_type type,
125 const esplusplayer_buffer_status status,
127 // auto buffer_status =
128 // status == ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN ? "underrun" :
130 // std::cout << "OnBufferStatus " << buffer_status << std::endl;
132 static void OnReadyToPrepare(const esplusplayer_stream_type type,
134 EsPlayerEventCallback* cb = static_cast<EsPlayerEventCallback*>(userdata);
135 std::cout << "OnReadyToPrepare" << std::endl;
136 std::unique_lock<std::mutex> lk(cb->data_m_);
137 if (type == ESPLUSPLAYER_STREAM_TYPE_AUDIO) {
138 cb->ready_audio_data_ = true;
139 if (cb->audio_reader_ != nullptr) {
140 cb->audio_feeding_task_ =
141 std::thread(DataFeedingTask, std::ref(cb->audio_reader_),
142 std::ref(cb->handle_));
144 std::cout << "Audio ready to prepare" << std::endl;
145 } else if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO) {
146 cb->ready_video_data_ = true;
147 if (cb->video_reader_ != nullptr) {
148 cb->video_feeding_task_ =
149 std::thread(DataFeedingTask, std::ref(cb->video_reader_),
150 std::ref(cb->handle_));
152 std::cout << "Video ready to prepare" << std::endl;
155 cb->data_cv_.notify_all();
157 static void OnReadyToSeek(const esplusplayer_stream_type type,
158 const uint64_t offset, void* userdata) {
159 EsPlayerEventCallback* cb = static_cast<EsPlayerEventCallback*>(userdata);
160 std::cout << "OnReadyToSeek" << std::endl;
161 std::unique_lock<std::mutex> lk(cb->data_m_);
162 if (type == ESPLUSPLAYER_STREAM_TYPE_AUDIO)
163 cb->ready_audio_data_ = true;
164 else if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO)
165 cb->ready_video_data_ = true;
167 cb->data_cv_.notify_all();
169 void WaitAllStreamData() {
170 std::unique_lock<std::mutex> lk(data_m_);
171 std::cout << "WaitAllStreamData start" << std::endl;
172 data_cv_.wait_for(lk, std::chrono::seconds(1), [this]() -> bool {
173 return ready_audio_data_ && ready_video_data_;
175 std::cout << "WaitAllStreamData stop" << std::endl;
178 void WaitAudioStreamData() {
179 std::unique_lock<std::mutex> lk(data_m_);
180 std::cout << "WaitAudioStreamData start" << std::endl;
181 data_cv_.wait_for(lk, std::chrono::seconds(1),
182 [this]() -> bool { return ready_audio_data_; });
183 std::cout << "WaitAudioStreamData stop" << std::endl;
186 void WaitVideoStreamData() {
187 std::unique_lock<std::mutex> lk(data_m_);
188 std::cout << "WaitVideoStreamData start" << std::endl;
189 data_cv_.wait_for(lk, std::chrono::seconds(1),
190 [this]() -> bool { return ready_audio_data_; });
191 std::cout << "WaitVideoStreamData stop" << std::endl;
195 std::cout << "WaitForEos start" << std::endl;
196 std::unique_lock<std::mutex> lk(eos_m_);
197 eos_cv_.wait_for(lk, std::chrono::minutes(1),
198 [this]() -> bool { return eos_; });
199 std::cout << "WaitForEos stop" << std::endl;
202 bool WaitForPrepareDone() {
203 std::cout << "WaitForPrepareDone start" << std::endl;
204 std::unique_lock<std::mutex> lk(prepare_done_m_);
205 prepare_done_cv_.wait_for(lk, std::chrono::seconds(10),
206 [this]() -> bool { return prepare_done_; });
207 std::cout << "WaitForPrepareDone stop" << std::endl;
209 return prepare_done_result_;
213 esplusplayer_handle handle_ = nullptr;
214 EsStreamReader* video_reader_ = nullptr;
215 EsStreamReader* audio_reader_ = nullptr;
216 std::thread video_feeding_task_;
217 std::thread audio_feeding_task_;
221 std::condition_variable eos_cv_;
222 bool ready_audio_data_ = false;
223 bool ready_video_data_ = false;
225 std::condition_variable data_cv_;
226 bool prepare_done_ = false;
227 bool prepare_done_result_ = false;
228 std::mutex prepare_done_m_;
229 std::condition_variable prepare_done_cv_;
232 #endif // __PLUSPLAYER_UT_INCLUDE_ES_EVENT_LISTENER_H__