blob: 94b0ea1a8966e423b92fd071a0176cc16df98e4c [file] [log] [blame]
hualing chenb31a6c62020-01-13 17:27:00 +08001#include <stdio.h>
2#include <stdlib.h>
3
hualing chen5cbe1a62020-02-10 16:36:36 +08004#include <string.h>
hualing chenb31a6c62020-01-13 17:27:00 +08005#include <sys/types.h>
6#include <sys/stat.h>
7#include <sys/ioctl.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <poll.h>
11#include <errno.h>
12#include <signal.h>
13#include <pthread.h>
14
hualing chen5cbe1a62020-02-10 16:36:36 +080015#include <amports/amstream.h>
hualing chenb31a6c62020-01-13 17:27:00 +080016
hualing chenb31a6c62020-01-13 17:27:00 +080017#include "dvr_playback.h"
18
19#define VALID_PID(_pid_) ((_pid_)>0 && (_pid_)<0x1fff)
20
hualing chen5cbe1a62020-02-10 16:36:36 +080021#define FFFB_SLEEP_TIME 400
22
23//
24static int _dvr_playback_fffb(DVR_PlaybackHandle_t handle);
hualing chencc91e1c2020-02-28 13:26:17 +080025static int _do_check_pid_info(DVR_PlaybackHandle_t handle, DVR_StreamInfo_t now_pid, DVR_StreamInfo_t set_pid, int type);
26static int _dvr_get_cur_time(DVR_PlaybackHandle_t handle);
27static int _dvr_get_end_time(DVR_PlaybackHandle_t handle);
28
hualing chen5cbe1a62020-02-10 16:36:36 +080029//convert video and audio fmt
30static int _dvr_convert_stream_fmt(int fmt, DVR_Bool_t is_audio) {
31 int format = 0;
32 if (is_audio == DVR_FALSE) {
33 //for video fmt
34 switch (fmt)
35 {
36 case DVR_VIDEO_FORMAT_MPEG1:
37 format = VFORMAT_MPEG12;
38 break;
39 case DVR_VIDEO_FORMAT_MPEG2:
40 format = VFORMAT_MPEG12;
41 break;
42 case DVR_VIDEO_FORMAT_HEVC:
43 format = VFORMAT_HEVC;
44 break;
45 case DVR_VIDEO_FORMAT_H264:
46 format = VFORMAT_H264;
47 break;
48 }
49 } else {
50 //for audio fmt
51 switch (fmt)
52 {
53 case DVR_AUDIO_FORMAT_MPEG:
54 format = AFORMAT_MPEG;
55 break;
56 case DVR_AUDIO_FORMAT_AC3:
57 format = AFORMAT_AC3;
58 break;
59 case DVR_AUDIO_FORMAT_EAC3:
60 format = AFORMAT_EAC3;
61 break;
62 case DVR_AUDIO_FORMAT_DTS:
63 format = AFORMAT_DTS;
64 break;
65 }
66 }
67 return format;
68}
hualing chen040df222020-01-17 13:35:02 +080069static int _dvr_playback_get_trick_stat(DVR_PlaybackHandle_t handle)
hualing chen86e7d482020-01-16 15:13:33 +080070{
71 int state;
hualing chen040df222020-01-17 13:35:02 +080072 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen86e7d482020-01-16 15:13:33 +080073
hualing chen5cbe1a62020-02-10 16:36:36 +080074 if (player->handle == NULL)
hualing chen86e7d482020-01-16 15:13:33 +080075 return -1;
76
77 state = playback_device_get_trick_stat(handle);
78
79 return state;
80}
hualing chen5cbe1a62020-02-10 16:36:36 +080081//get sys time ms
82static int _dvr_time_getClock(void)
83{
84 struct timespec ts;
85 int ms;
86
87 clock_gettime(CLOCK_MONOTONIC, &ts);
88 ms = ts.tv_sec*1000+ts.tv_nsec/1000000;
89
90 return ms;
91}
hualing chen86e7d482020-01-16 15:13:33 +080092
hualing chenb31a6c62020-01-13 17:27:00 +080093
94//timeout wait sibnal
hualing chen040df222020-01-17 13:35:02 +080095static int _dvr_playback_timeoutwait(DVR_PlaybackHandle_t handle , int ms)
hualing chenb31a6c62020-01-13 17:27:00 +080096{
hualing chen040df222020-01-17 13:35:02 +080097 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +080098
hualing chen86e7d482020-01-16 15:13:33 +080099 struct timespec ts;
100 clock_gettime(CLOCK_MONOTONIC, &ts);
101 //ms为毫秒,换算成秒
102 ts.tv_sec += ms/1000;
103 //在outtime的基础上,增加ms毫秒
104 //outtime.tv_nsec为纳秒,1微秒=1000纳秒
105 //tv_nsec此值再加上剩余的毫秒数 ms%1000,有可能超过1秒。需要特殊处理
106 uint64_t us = ts.tv_nsec/1000 + 1000 * (ms % 1000); //微秒
107 //us的值有可能超过1秒,
108 ts.tv_sec += us / 1000000;
109 us = us % 1000000;
110 ts.tv_nsec = us * 1000;//换算成纳秒
hualing chen86e7d482020-01-16 15:13:33 +0800111 pthread_cond_timedwait(&player->cond, &player->lock, &ts);
112 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800113}
114
115//send signal
hualing chen040df222020-01-17 13:35:02 +0800116static int _dvr_playback_sendSignal(DVR_PlaybackHandle_t handle)
hualing chenb31a6c62020-01-13 17:27:00 +0800117{
hualing chen040df222020-01-17 13:35:02 +0800118 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800119 //pthread_cond_signal(&player->cond);
hualing chen86e7d482020-01-16 15:13:33 +0800120 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800121}
122
hualing chencc91e1c2020-02-28 13:26:17 +0800123//send playback event
124static int _dvr_playback_sent_event(DVR_PlaybackHandle_t handle, DVR_PlaybackEvent_t evt, DVR_Play_Notify_t *notify) {
125
126 DVR_Playback_t *player = (DVR_Playback_t *) handle;
127 DVR_DEBUG(1, "into send event -----");
128 switch (evt) {
129 case DVR_PLAYBACK_EVENT_ERROR:
130 break;
131 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
132 //GET STATE
133 DVR_DEBUG(1, "trans ok----");
134 dvr_playback_get_status(handle, &(notify->play_status));
135 break;
136 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
137 break;
138 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
139 break;
140 case DVR_PLAYBACK_EVENT_NO_KEY:
141 break;
142 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
143 break;
144 case DVR_PLAYBACK_EVENT_REACHED_END:
145 //GET STATE
146 DVR_DEBUG(1, "reached end---");
147 dvr_playback_get_status(handle, &(notify->play_status));
148 break;
149 default:
150 break;
151 }
152 if (player->openParams.event_fn != NULL)
153 player->openParams.event_fn(evt, (void*)notify, player->openParams.event_userdata);
154 DVR_DEBUG(1, "into send event --end---");
155 return DVR_SUCCESS;
156}
157static int _dvr_playback_sent_transition_ok(DVR_PlaybackHandle_t handle)
158{
159 DVR_Play_Notify_t notify;
160 memset(&notify, 0 , sizeof(DVR_Play_Notify_t));
161 notify.event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
162 //get play statue not here
163 _dvr_playback_sent_event(handle, DVR_PLAYBACK_EVENT_TRANSITION_OK, &notify);
164 return DVR_SUCCESS;
165}
166
167//check is ongoing segment
168static int _dvr_check_segment_ongoing(DVR_PlaybackHandle_t handle) {
169
170 DVR_Playback_t *player = (DVR_Playback_t *) handle;
171 Segment_StoreInfo_t info;
172 int ret = DVR_FALSE;
173 DVR_DEBUG(1, "into check ongoing---");
174 if (player->r_handle != NULL)
175 ret = segment_load_info(player->r_handle, &info);
176
177 if (ret != DVR_SUCCESS) {
178 DVR_DEBUG(1, "is not ongoing chunk--end---");
179 return DVR_FALSE;
180 }
181 DVR_DEBUG(1, "is ongoing chunk--end---");
182 return DVR_TRUE;
183}
184//get next segment id
hualing chen040df222020-01-17 13:35:02 +0800185static int _dvr_get_next_segmentId(DVR_PlaybackHandle_t handle) {
hualing chenb31a6c62020-01-13 17:27:00 +0800186
hualing chen040df222020-01-17 13:35:02 +0800187 DVR_Playback_t *player = (DVR_Playback_t *) handle;
188 DVR_PlaybackSegmentInfo_t *segment;
hualing chen86e7d482020-01-16 15:13:33 +0800189
190 int found = 0;
191
hualing chen040df222020-01-17 13:35:02 +0800192 list_for_each_entry(segment, &player->segment_list, head)
hualing chen86e7d482020-01-16 15:13:33 +0800193 {
hualing chencc91e1c2020-02-28 13:26:17 +0800194 if (player->segment_is_open == DVR_FALSE) {
hualing chen040df222020-01-17 13:35:02 +0800195 //get first segment from list
hualing chen86e7d482020-01-16 15:13:33 +0800196 found = 1;
hualing chen040df222020-01-17 13:35:02 +0800197 } else if (segment->segment_id == player->cur_segment_id) {
198 //find cur segment, we need get next one
hualing chen86e7d482020-01-16 15:13:33 +0800199 found = 1;
200 continue;
201 }
202 if (found == 1) {
hualing chencc91e1c2020-02-28 13:26:17 +0800203 //save segment info
204 player->last_segment_id = player->cur_segment_id;
205 player->last_segment.segment_id = player->cur_segment.flags;
206 player->last_segment.flags = segment->flags;
207 memcpy(player->last_segment.location, player->cur_segment.location, DVR_MAX_LOCATION_SIZE);
208 //pids
209 memcpy(&player->last_segment.pids, &player->cur_segment.pids, sizeof(DVR_PlaybackPids_t));
210
hualing chen5cbe1a62020-02-10 16:36:36 +0800211 //get segment info
hualing chencc91e1c2020-02-28 13:26:17 +0800212 player->segment_is_open = DVR_TRUE;
hualing chen040df222020-01-17 13:35:02 +0800213 player->cur_segment_id = segment->segment_id;
214 player->cur_segment.segment_id = segment->segment_id;
215 player->cur_segment.flags = segment->flags;
hualing chencc91e1c2020-02-28 13:26:17 +0800216 DVR_DEBUG(1, "cur flag[0x%x]segment->flags flag[0x%x] id [%lld]", player->cur_segment.flags, segment->flags, segment->segment_id);
hualing chen5cbe1a62020-02-10 16:36:36 +0800217 memcpy(player->cur_segment.location, segment->location, DVR_MAX_LOCATION_SIZE);
hualing chen86e7d482020-01-16 15:13:33 +0800218 //pids
hualing chen040df222020-01-17 13:35:02 +0800219 memcpy(&player->cur_segment.pids, &segment->pids, sizeof(DVR_PlaybackPids_t));
hualing chen86e7d482020-01-16 15:13:33 +0800220 found = 2;
221 }
222 }
223 if (found != 2) {
224 //list is null or reache list end
225 return -1;
226 }
227 return DVR_SUCCESS;
228}
hualing chen040df222020-01-17 13:35:02 +0800229//open next segment to play,if reach list end return errro.
230static int _change_to_next_segment(DVR_PlaybackHandle_t handle)
hualing chen86e7d482020-01-16 15:13:33 +0800231{
hualing chen040df222020-01-17 13:35:02 +0800232 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen86e7d482020-01-16 15:13:33 +0800233 Segment_OpenParams_t params;
234 int ret = DVR_SUCCESS;
235
hualing chen040df222020-01-17 13:35:02 +0800236 int id = _dvr_get_next_segmentId(handle);
hualing chen86e7d482020-01-16 15:13:33 +0800237 if (id < 0) {
hualing chen040df222020-01-17 13:35:02 +0800238 DVR_DEBUG(1, "not found segment info");
hualing chen5cbe1a62020-02-10 16:36:36 +0800239 return DVR_FAILURE;
hualing chen86e7d482020-01-16 15:13:33 +0800240 }
241
242 if (player->r_handle != NULL) {
243 segment_close(player->r_handle);
244 player->r_handle = NULL;
245 }
246
247 memset(params.location, 0, DVR_MAX_LOCATION_SIZE);
hualing chen5cbe1a62020-02-10 16:36:36 +0800248 //cp chur segment path to location
249 memcpy(params.location, player->cur_segment.location, DVR_MAX_LOCATION_SIZE);
hualing chen040df222020-01-17 13:35:02 +0800250 params.segment_id = (uint64_t)player->cur_segment.segment_id;
hualing chen86e7d482020-01-16 15:13:33 +0800251 params.mode = SEGMENT_MODE_READ;
hualing chencc91e1c2020-02-28 13:26:17 +0800252 DVR_DEBUG(1, "open segment info[%s][%lld]flag[0x%x]", params.location, params.segment_id, player->cur_segment.flags);
hualing chen86e7d482020-01-16 15:13:33 +0800253 ret = segment_open(&params, &(player->r_handle));
hualing chencc91e1c2020-02-28 13:26:17 +0800254 Segment_StoreInfo_t info;
255 if (segment_load_info(player->r_handle, &info) == DVR_SUCCESS) {
256 player->openParams.is_timeshift = DVR_FALSE;
257 } else {
258 player->openParams.is_timeshift = DVR_TRUE;
259 }
260 player->dur = info.duration;
261 DVR_DEBUG(1, "next player->dur [%d] flag [0x%x]", player->dur, player->cur_segment.flags);
hualing chen86e7d482020-01-16 15:13:33 +0800262 return ret;
263}
264
hualing chen5cbe1a62020-02-10 16:36:36 +0800265//open next segment to play,if reach list end return errro.
266static int _dvr_open_segment(DVR_PlaybackHandle_t handle, uint64_t segment_id)
267{
268 DVR_Playback_t *player = (DVR_Playback_t *) handle;
269 Segment_OpenParams_t params;
270 int ret = DVR_SUCCESS;
hualing chencc91e1c2020-02-28 13:26:17 +0800271 if (segment_id == player->cur_segment_id && player->segment_is_open == DVR_TRUE) {
hualing chen5cbe1a62020-02-10 16:36:36 +0800272 return 0;
273 }
hualing chencc91e1c2020-02-28 13:26:17 +0800274 uint64_t id = segment_id;
hualing chen5cbe1a62020-02-10 16:36:36 +0800275 if (id < 0) {
276 DVR_DEBUG(1, "not found segment info");
277 return DVR_FAILURE;
278 }
hualing chencc91e1c2020-02-28 13:26:17 +0800279 DVR_DEBUG(1, "start found segment[%lld][%lld] info", id,segment_id);
hualing chen5cbe1a62020-02-10 16:36:36 +0800280
281 if (player->r_handle != NULL) {
282 segment_close(player->r_handle);
283 player->r_handle = NULL;
284 }
285
286 DVR_PlaybackSegmentInfo_t *segment;
287
288 int found = 0;
hualing chencc91e1c2020-02-28 13:26:17 +0800289
hualing chen5cbe1a62020-02-10 16:36:36 +0800290 list_for_each_entry(segment, &player->segment_list, head)
291 {
hualing chencc91e1c2020-02-28 13:26:17 +0800292 DVR_DEBUG(1, "see 1 location [%s]id[%lld]flag[%x]segment_id[%lld]", segment->location, segment->segment_id, segment->flags, segment_id);
hualing chen5cbe1a62020-02-10 16:36:36 +0800293 if (segment->segment_id == segment_id) {
294 found = 1;
295 }
296 if (found == 1) {
hualing chencc91e1c2020-02-28 13:26:17 +0800297 DVR_DEBUG(1, "found [%s]id[%lld]flag[%x]segment_id[%lld]", segment->location, segment->segment_id, segment->flags, segment_id);
hualing chen5cbe1a62020-02-10 16:36:36 +0800298 //get segment info
hualing chencc91e1c2020-02-28 13:26:17 +0800299 player->segment_is_open = DVR_TRUE;
hualing chen5cbe1a62020-02-10 16:36:36 +0800300 player->cur_segment_id = segment->segment_id;
301 player->cur_segment.segment_id = segment->segment_id;
302 player->cur_segment.flags = segment->flags;
hualing chencc91e1c2020-02-28 13:26:17 +0800303 strncpy(player->cur_segment.location, segment->location, strlen(segment->location));//DVR_MAX_LOCATION_SIZE
hualing chen5cbe1a62020-02-10 16:36:36 +0800304 //pids
305 memcpy(&player->cur_segment.pids, &segment->pids, sizeof(DVR_PlaybackPids_t));
hualing chencc91e1c2020-02-28 13:26:17 +0800306 DVR_DEBUG(1, "cur found location [%s]id[%lld]flag[%x]", player->cur_segment.location, player->cur_segment.segment_id,player->cur_segment.flags);
307 break;
hualing chen5cbe1a62020-02-10 16:36:36 +0800308 }
309 }
hualing chencc91e1c2020-02-28 13:26:17 +0800310 if (found == 0) {
311 DVR_DEBUG(1, "not found segment info.error..");
312 return DVR_FAILURE;
313 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800314 memset(params.location, 0, DVR_MAX_LOCATION_SIZE);
hualing chencc91e1c2020-02-28 13:26:17 +0800315 //cp cur segment path to location
hualing chen5cbe1a62020-02-10 16:36:36 +0800316 strncpy(params.location, player->cur_segment.location, strlen(player->cur_segment.location));
317 params.segment_id = (uint64_t)player->cur_segment.segment_id;
318 params.mode = SEGMENT_MODE_READ;
hualing chencc91e1c2020-02-28 13:26:17 +0800319 DVR_DEBUG(1, "open segment location[%s][%lld]cur flag[0x%x]", params.location, params.segment_id, player->cur_segment.flags);
hualing chen5cbe1a62020-02-10 16:36:36 +0800320 ret = segment_open(&params, &(player->r_handle));
hualing chencc91e1c2020-02-28 13:26:17 +0800321 Segment_StoreInfo_t info;
322 if (segment_load_info(player->r_handle, &info) == DVR_SUCCESS) {
323 player->openParams.is_timeshift = DVR_FALSE;
324 } else {
325 player->openParams.is_timeshift = DVR_TRUE;
326 }
327 player->dur = info.duration;
328
329 DVR_DEBUG(1, "player->dur [%d]cur id [%lld]cur flag [0x%x]\r\n", player->dur,player->cur_segment.segment_id, player->cur_segment.flags);
hualing chen5cbe1a62020-02-10 16:36:36 +0800330 return ret;
331}
332
333
334//get play info by segment id
335static int _dvr_playback_get_playinfo(DVR_PlaybackHandle_t handle,
336 uint64_t segment_id,
337 Playback_DeviceVideoParams_t *vparam,
338 Playback_DeviceAudioParams_t *aparam) {
339
340 DVR_Playback_t *player = (DVR_Playback_t *) handle;
341 DVR_PlaybackSegmentInfo_t *segment;
342
343 int found = 0;
344
345 list_for_each_entry(segment, &player->segment_list, head)
346 {
hualing chencc91e1c2020-02-28 13:26:17 +0800347 if (segment_id == 0LL) {
hualing chen5cbe1a62020-02-10 16:36:36 +0800348 //get first segment from list
349 found = 1;
350 }
351 if (segment->segment_id == segment_id) {
352 found = 1;
353 }
354 if (found == 1) {
355 //get segment info
356 if (player->cur_segment_id > 0)
357 player->cur_segment_id = segment->segment_id;
358 DVR_DEBUG(1, "get play info id [%lld]", player->cur_segment_id);
359 player->cur_segment.segment_id = segment->segment_id;
360 player->cur_segment.flags = segment->flags;
361 //pids
362 memcpy(&player->cur_segment.pids, &segment->pids, sizeof(DVR_PlaybackPids_t));
363 //
364 vparam->fmt = _dvr_convert_stream_fmt(segment->pids.video.format, DVR_FALSE);
365 vparam->pid = segment->pids.video.pid;
366 aparam->fmt = _dvr_convert_stream_fmt(segment->pids.audio.format, DVR_TRUE);
367 aparam->pid = segment->pids.audio.pid;
hualing chencc91e1c2020-02-28 13:26:17 +0800368 DVR_DEBUG(1, "get play info sucess[0x%x]apid[0x%x]", vparam->pid, aparam->pid);
hualing chen5cbe1a62020-02-10 16:36:36 +0800369 found = 2;
hualing chencc91e1c2020-02-28 13:26:17 +0800370 break;
hualing chen5cbe1a62020-02-10 16:36:36 +0800371 }
372 }
hualing chencc91e1c2020-02-28 13:26:17 +0800373 if (found != 2) {
374 //list is null or reache list end
375 DVR_DEBUG(1, "get play info fail");
376 return DVR_FAILURE;
377 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800378
379 return DVR_SUCCESS;
380}
hualing chencc91e1c2020-02-28 13:26:17 +0800381static int _dvr_replay_changed_pid(DVR_PlaybackHandle_t handle) {
382 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen5cbe1a62020-02-10 16:36:36 +0800383
hualing chencc91e1c2020-02-28 13:26:17 +0800384 //compare cur segment
385 //if (player->cmd.state == DVR_PLAYBACK_STATE_START)
386 {
387 //check video pids, stop or restart
388 _do_check_pid_info(handle, player->last_segment.pids.video, player->cur_segment.pids.video, 0);
389 //check audio pids stop or restart
390 _do_check_pid_info(handle, player->last_segment.pids.audio, player->cur_segment.pids.audio, 1);
391 //check sub audio pids stop or restart
392 _do_check_pid_info(handle, player->last_segment.pids.ad, player->cur_segment.pids.ad, 2);
393 //check pcr pids stop or restart
394 _do_check_pid_info(handle, player->last_segment.pids.pcr, player->cur_segment.pids.pcr, 3);
395 }
396 return 0;
397}
hualing chen5cbe1a62020-02-10 16:36:36 +0800398
hualing chencc91e1c2020-02-28 13:26:17 +0800399static int _dvr_check_cur_segment_flag(DVR_PlaybackHandle_t handle)
400{
401 DVR_Playback_t *player = (DVR_Playback_t *) handle;
402 DVR_DEBUG(1, "call %s flag[0x%x]id[%lld]", __func__, player->cur_segment.flags, player->cur_segment.segment_id);
403 if ((player->cur_segment.flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == DVR_PLAYBACK_SEGMENT_DISPLAYABLE) {
404 //disable display
405 DVR_DEBUG(1, "call %s unmute", __func__);
406 playback_device_mute_audio(player->handle, 0);
407 playback_device_mute_video(player->handle, 0);
408 } else if ((player->cur_segment.flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == 0) {
409 //enable display
410 DVR_DEBUG(1, "call %s mute", __func__);
411 playback_device_mute_audio(player->handle, 1);
412 playback_device_mute_video(player->handle, 1);
413 }
414 return DVR_SUCCESS;
415}
hualing chen86e7d482020-01-16 15:13:33 +0800416static void* _dvr_playback_thread(void *arg)
417{
hualing chen040df222020-01-17 13:35:02 +0800418 DVR_Playback_t *player = (DVR_Playback_t *) arg;
hualing chencc91e1c2020-02-28 13:26:17 +0800419 //int need_open_segment = 1;
hualing chen040df222020-01-17 13:35:02 +0800420 Playback_DeviceWBufs_t wbufs;
hualing chen5cbe1a62020-02-10 16:36:36 +0800421 int ret = DVR_SUCCESS;
hualing chen86e7d482020-01-16 15:13:33 +0800422
hualing chencc91e1c2020-02-28 13:26:17 +0800423 int timeout = 50;//ms
hualing chen86e7d482020-01-16 15:13:33 +0800424 uint8_t *buf = NULL;
hualing chen040df222020-01-17 13:35:02 +0800425 int buf_len = player->openParams.block_size > 0 ? player->openParams.block_size : (256 * 1024);
hualing chen86e7d482020-01-16 15:13:33 +0800426 int real_read = 0;
427 int real_write = 0;
428
hualing chen86e7d482020-01-16 15:13:33 +0800429 buf = malloc(buf_len);
430 wbufs.flag = 0;
431 wbufs.timeout = 10;
432 wbufs.len = 0;
hualing chencc91e1c2020-02-28 13:26:17 +0800433
434 if (player->segment_is_open == DVR_FALSE) {
hualing chen5cbe1a62020-02-10 16:36:36 +0800435 ret = _change_to_next_segment((DVR_PlaybackHandle_t)player);
436 }
hualing chen86e7d482020-01-16 15:13:33 +0800437
hualing chen86e7d482020-01-16 15:13:33 +0800438 if (ret != DVR_SUCCESS) {
439 if (buf != NULL) {
440 free(buf);
441 buf = NULL;
442 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800443 DVR_DEBUG(1, "get segment error");
hualing chenb31a6c62020-01-13 17:27:00 +0800444 return NULL;
hualing chen86e7d482020-01-16 15:13:33 +0800445 }
hualing chencc91e1c2020-02-28 13:26:17 +0800446 //get play statue not here
447 _dvr_playback_sent_transition_ok((DVR_PlaybackHandle_t)player);
448 _dvr_check_cur_segment_flag((DVR_PlaybackHandle_t)player);
hualing chen5cbe1a62020-02-10 16:36:36 +0800449
hualing chen86e7d482020-01-16 15:13:33 +0800450 int trick_stat = 0;
451 while (player->is_running/* || player->cmd.last_cmd != player->cmd.cur_cmd*/) {
hualing chenb31a6c62020-01-13 17:27:00 +0800452
hualing chen86e7d482020-01-16 15:13:33 +0800453 //check trick stat
hualing chencc91e1c2020-02-28 13:26:17 +0800454 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800455 trick_stat = _dvr_playback_get_trick_stat((DVR_PlaybackHandle_t)player);
hualing chen5cbe1a62020-02-10 16:36:36 +0800456
hualing chen86e7d482020-01-16 15:13:33 +0800457 if (trick_stat > 0)
458 {
hualing chen040df222020-01-17 13:35:02 +0800459 if (player->cmd.cur_cmd == DVR_PLAYBACK_CMD_SEEK) {
hualing chen86e7d482020-01-16 15:13:33 +0800460 //check last cmd
hualing chen040df222020-01-17 13:35:02 +0800461 if(player->cmd.last_cmd == DVR_PLAYBACK_CMD_PAUSE
462 || (player->play_flag == DVR_PLAYBACK_STARTED_PAUSEDLIVE
463 && (player->cmd.last_cmd == DVR_PLAYBACK_CMD_VSTART
464 || player->cmd.last_cmd == DVR_PLAYBACK_CMD_ASTART
465 || player->cmd.last_cmd == DVR_PLAYBACK_CMD_START))) {
hualing chenb31a6c62020-01-13 17:27:00 +0800466
hualing chen86e7d482020-01-16 15:13:33 +0800467 //need change to pause state
hualing chen040df222020-01-17 13:35:02 +0800468 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_PAUSE;
469 player->cmd.state = DVR_PLAYBACK_STATE_PAUSE;
hualing chen86e7d482020-01-16 15:13:33 +0800470 playback_device_pause(player->handle);
471 }
hualing chen040df222020-01-17 13:35:02 +0800472 } else if (player->cmd.cur_cmd == DVR_PLAYBACK_CMD_FF
473 || player->cmd.cur_cmd == DVR_PLAYBACK_CMD_FB) {
hualing chen86e7d482020-01-16 15:13:33 +0800474 //restart play stream if speed > 2
hualing chencc91e1c2020-02-28 13:26:17 +0800475 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +0800476 _dvr_playback_fffb((DVR_PlaybackHandle_t)player);
hualing chencc91e1c2020-02-28 13:26:17 +0800477 pthread_mutex_lock(&player->lock);
478 }
hualing chenb31a6c62020-01-13 17:27:00 +0800479 }
hualing chen86e7d482020-01-16 15:13:33 +0800480
481 int write = 0;
482 int read = segment_read(player->r_handle, buf + real_read, buf_len - real_read);
hualing chencc91e1c2020-02-28 13:26:17 +0800483 pthread_mutex_unlock(&player->lock);
484
485 //DVR_DEBUG(1, "read ts [%d]buf_len[%d]", read, buf_len);
hualing chen86e7d482020-01-16 15:13:33 +0800486 if (read == 0) {
hualing chencc91e1c2020-02-28 13:26:17 +0800487 //file end.need to play next segment
hualing chen040df222020-01-17 13:35:02 +0800488 int ret = _change_to_next_segment((DVR_PlaybackHandle_t)player);
hualing chen86e7d482020-01-16 15:13:33 +0800489 if (ret != DVR_SUCCESS) {
490 if (player->openParams.is_timeshift) {
hualing chencc91e1c2020-02-28 13:26:17 +0800491 //send end event to hal
492 DVR_Play_Notify_t notify;
493 memset(&notify, 0 , sizeof(DVR_Play_Notify_t));
494 notify.event = DVR_PLAYBACK_EVENT_REACHED_END;
495 //get play statue not here
496 _dvr_playback_sent_event((DVR_PlaybackHandle_t)player, DVR_PLAYBACK_EVENT_REACHED_END, &notify);
497
hualing chen040df222020-01-17 13:35:02 +0800498 //continue,timeshift mode, when read end,need wait cur recording segment
hualing chencc91e1c2020-02-28 13:26:17 +0800499 DVR_DEBUG(1, "playback is timeshift");
500 pthread_mutex_lock(&player->lock);
501 _dvr_playback_timeoutwait((DVR_PlaybackHandle_t)player, timeout);
502 pthread_mutex_unlock(&player->lock);
hualing chen86e7d482020-01-16 15:13:33 +0800503 continue;
504 } else {
505 //play end
hualing chencc91e1c2020-02-28 13:26:17 +0800506 if (read == 0) {
507 DVR_DEBUG(1, "playback reach end segment, exit playbackplayer->cur_segment_id [%lld] [%p]", player->cur_segment_id, (DVR_PlaybackHandle_t)player);
508 //send reach end
509 DVR_Play_Notify_t notify;
510 memset(&notify, 0 , sizeof(DVR_Play_Notify_t));
511 notify.event = DVR_PLAYBACK_EVENT_REACHED_END;
512 //get play statue not here
513 _dvr_playback_sent_event((DVR_PlaybackHandle_t)player, DVR_PLAYBACK_EVENT_REACHED_END, &notify);
514 DVR_DEBUG(1, "playback reach end segment, send event end");
515 continue;
hualing chen86e7d482020-01-16 15:13:33 +0800516 } else {
517 //has data not inject to dev
518 goto inject;
519 }
520 }
521 }
hualing chencc91e1c2020-02-28 13:26:17 +0800522 _dvr_playback_sent_transition_ok((DVR_PlaybackHandle_t)player);
523 pthread_mutex_lock(&player->lock);
524 _dvr_replay_changed_pid((DVR_PlaybackHandle_t)player);
525 _dvr_check_cur_segment_flag((DVR_PlaybackHandle_t)player);
hualing chen86e7d482020-01-16 15:13:33 +0800526 read = segment_read(player->r_handle, buf + real_read, buf_len - real_read);
hualing chencc91e1c2020-02-28 13:26:17 +0800527 pthread_mutex_lock(&player->lock);
528
hualing chen86e7d482020-01-16 15:13:33 +0800529 }
530 real_read = real_read + read;
531 if (real_read < buf_len ) {
hualing chencc91e1c2020-02-28 13:26:17 +0800532 if (player->openParams.is_timeshift) {
533 //send end event to hal
534 DVR_Play_Notify_t notify;
535 memset(&notify, 0 , sizeof(DVR_Play_Notify_t));
536 notify.event = DVR_PLAYBACK_EVENT_REACHED_END;
537 //get play statue not here
538 _dvr_playback_sent_event((DVR_PlaybackHandle_t)player, DVR_PLAYBACK_EVENT_REACHED_END, &notify);
539
540 //continue,timeshift mode, when read end,need wait cur recording segment
541 DVR_DEBUG(1, "playback is timeshift---");
542 pthread_mutex_lock(&player->lock);
543 _dvr_playback_timeoutwait((DVR_PlaybackHandle_t)player, timeout);
544 pthread_mutex_unlock(&player->lock);
545 continue;
546 }
hualing chen86e7d482020-01-16 15:13:33 +0800547 //continue to read
hualing chencc91e1c2020-02-28 13:26:17 +0800548 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800549 _dvr_playback_timeoutwait((DVR_PlaybackHandle_t)player, timeout);
hualing chencc91e1c2020-02-28 13:26:17 +0800550 pthread_mutex_unlock(&player->lock);
hualing chen86e7d482020-01-16 15:13:33 +0800551 if (!player->is_running) {
552 break;
553 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800554 DVR_DEBUG(1, "playback continue read");
hualing chen86e7d482020-01-16 15:13:33 +0800555 continue;
556 }
557inject:
558 wbufs.len = real_read;
559 real_write = 0;
560rewrite:
561 wbufs.buf = buf + real_write;
562 //read data
563 //descramble data
564 //read data to inject
hualing chencc91e1c2020-02-28 13:26:17 +0800565 //DVR_DEBUG(1, "playback dev write---");
hualing chen86e7d482020-01-16 15:13:33 +0800566 write = playback_device_write(player->handle, &wbufs);
567 real_write = real_write + write;
568 wbufs.len = real_read - real_write;
569 //check if left data
570 if (real_write == real_read) {
571 //this block write end
hualing chen5cbe1a62020-02-10 16:36:36 +0800572 real_read = 0;
573 real_write = 0;
574 continue;
hualing chen86e7d482020-01-16 15:13:33 +0800575 } else {
hualing chencc91e1c2020-02-28 13:26:17 +0800576 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800577 _dvr_playback_timeoutwait((DVR_PlaybackHandle_t)player, timeout);
hualing chencc91e1c2020-02-28 13:26:17 +0800578 pthread_mutex_unlock(&player->lock);
hualing chen86e7d482020-01-16 15:13:33 +0800579 if (!player->is_running) {
580 break;
581 }
582 goto rewrite;
583 }
584 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800585 DVR_DEBUG(1, "playback thread is end");
hualing chen86e7d482020-01-16 15:13:33 +0800586 return NULL;
hualing chenb31a6c62020-01-13 17:27:00 +0800587}
588
589
hualing chen040df222020-01-17 13:35:02 +0800590static int _start_playback_thread(DVR_PlaybackHandle_t handle)
hualing chenb31a6c62020-01-13 17:27:00 +0800591{
hualing chen040df222020-01-17 13:35:02 +0800592 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800593 DVR_DEBUG(1, "start thread------[%d]", player->is_running);
594 if (player->is_running == DVR_TRUE) {
hualing chen86e7d482020-01-16 15:13:33 +0800595 return 0;
596 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800597 player->is_running = DVR_TRUE;
hualing chen86e7d482020-01-16 15:13:33 +0800598 int rc = pthread_create(&player->playback_thread, NULL, _dvr_playback_thread, (void*)player);
hualing chen5cbe1a62020-02-10 16:36:36 +0800599 if (rc < 0)
600 player->is_running = DVR_FALSE;
hualing chencc91e1c2020-02-28 13:26:17 +0800601 DVR_DEBUG(1, "start thread------[%d] end", player->is_running);
hualing chen86e7d482020-01-16 15:13:33 +0800602 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800603}
604
605
hualing chen040df222020-01-17 13:35:02 +0800606static int _stop_playback_thread(DVR_PlaybackHandle_t handle)
hualing chen86e7d482020-01-16 15:13:33 +0800607{
hualing chen040df222020-01-17 13:35:02 +0800608 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800609 DVR_DEBUG(1, "stopthread------[%d]", player->is_running);
610 if (player->is_running == DVR_TRUE)
hualing chen86e7d482020-01-16 15:13:33 +0800611 {
612 player->is_running = DVR_FALSE;
hualing chencc91e1c2020-02-28 13:26:17 +0800613 //pthread_cond_signal(&player->cond);
hualing chen86e7d482020-01-16 15:13:33 +0800614 pthread_join(player->playback_thread, NULL);
615 }
616 if (player->r_handle) {
617 segment_close(player->r_handle);
618 player->r_handle = NULL;
619 }
620 return 0;
621}
622
hualing chenb31a6c62020-01-13 17:27:00 +0800623/**\brief Open an dvr palyback
624 * \param[out] p_handle dvr playback addr
625 * \param[in] params dvr playback open parameters
626 * \retval DVR_SUCCESS On success
627 * \return Error code
628 */
hualing chen040df222020-01-17 13:35:02 +0800629int dvr_playback_open(DVR_PlaybackHandle_t *p_handle, DVR_PlaybackOpenParams_t *params) {
hualing chenb31a6c62020-01-13 17:27:00 +0800630
hualing chen040df222020-01-17 13:35:02 +0800631 DVR_Playback_t *player;
hualing chen86e7d482020-01-16 15:13:33 +0800632 pthread_condattr_t cattr;
hualing chenb31a6c62020-01-13 17:27:00 +0800633
hualing chen040df222020-01-17 13:35:02 +0800634 player = (DVR_Playback_t*)malloc(sizeof(DVR_Playback_t));
hualing chenb31a6c62020-01-13 17:27:00 +0800635
hualing chen86e7d482020-01-16 15:13:33 +0800636 pthread_mutex_init(&player->lock, NULL);
637 pthread_condattr_init(&cattr);
638 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
639 pthread_cond_init(&player->cond, &cattr);
640 pthread_condattr_destroy(&cattr);
hualing chenb31a6c62020-01-13 17:27:00 +0800641
hualing chen5cbe1a62020-02-10 16:36:36 +0800642 //init segment list head
hualing chen040df222020-01-17 13:35:02 +0800643 INIT_LIST_HEAD(&player->segment_list);
644 player->cmd.last_cmd = DVR_PLAYBACK_CMD_STOP;
645 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_STOP;
hualing chen5cbe1a62020-02-10 16:36:36 +0800646 player->cmd.speed.speed.speed = PLAYBACK_SPEED_X1;
hualing chen040df222020-01-17 13:35:02 +0800647 player->cmd.state = DVR_PLAYBACK_STATE_STOP;
hualing chen86e7d482020-01-16 15:13:33 +0800648 player->cmd.pos = 0;
649 //store open params
hualing chen040df222020-01-17 13:35:02 +0800650 player->openParams.dmx_dev_id = params->dmx_dev_id;
651 player->openParams.block_size = params->block_size;
hualing chen86e7d482020-01-16 15:13:33 +0800652 player->openParams.is_timeshift = params->is_timeshift;
hualing chencc91e1c2020-02-28 13:26:17 +0800653 player->openParams.event_fn = params->event_fn;
654 player->openParams.event_userdata = params->event_userdata;
655
hualing chen5cbe1a62020-02-10 16:36:36 +0800656 player->has_pids = params->has_pids;
657
hualing chen040df222020-01-17 13:35:02 +0800658 player->handle = params->playback_handle;
659
hualing chen86e7d482020-01-16 15:13:33 +0800660 //init has audio and video
661 player->has_video = DVR_FALSE;
662 player->has_audio = DVR_FALSE;
hualing chencc91e1c2020-02-28 13:26:17 +0800663 player->cur_segment_id = 0LL;
664 player->last_segment_id = 0LL;
665 player->segment_is_open = DVR_FALSE;
hualing chenb31a6c62020-01-13 17:27:00 +0800666
hualing chen5cbe1a62020-02-10 16:36:36 +0800667 //init ff fb time
668 player->fffb_current = -1;
669 player->fffb_start =-1;
670 player->fffb_start_pcr = -1;
671 //seek time
672 player->seek_time = 0;
hualing chen86e7d482020-01-16 15:13:33 +0800673 *p_handle = player;
674 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800675}
676
677/**\brief Close an dvr palyback
678 * \param[in] handle playback handle
679 * \retval DVR_SUCCESS On success
680 * \return Error code
681 */
hualing chen040df222020-01-17 13:35:02 +0800682int dvr_playback_close(DVR_PlaybackHandle_t handle) {
hualing chenb31a6c62020-01-13 17:27:00 +0800683
hualing chen86e7d482020-01-16 15:13:33 +0800684 DVR_ASSERT(handle);
hualing chenb31a6c62020-01-13 17:27:00 +0800685
hualing chen040df222020-01-17 13:35:02 +0800686 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800687 DVR_DEBUG(1, "func: %s", __func__);
688 if (player->state != DVR_PLAYBACK_STATE_STOP)
689 {
690 dvr_playback_stop(handle, DVR_TRUE);
691 }
hualing chen86e7d482020-01-16 15:13:33 +0800692 playback_device_close(player->handle);
693 //device close
694 pthread_mutex_destroy(&player->lock);
695 pthread_cond_destroy(&player->cond);
hualing chen040df222020-01-17 13:35:02 +0800696
697 if (player) {
698 free(player);
699 player = NULL;
700 }
hualing chen86e7d482020-01-16 15:13:33 +0800701 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800702}
703
hualing chenb31a6c62020-01-13 17:27:00 +0800704/**\brief Start play audio and video, used start auido api and start video api
705 * \param[in] handle playback handle
706 * \param[in] params audio playback params,contains fmt and pid...
707 * \retval DVR_SUCCESS On success
708 * \return Error code
709 */
hualing chen040df222020-01-17 13:35:02 +0800710int dvr_playback_start(DVR_PlaybackHandle_t handle, DVR_PlaybackFlag_t flag) {
711 DVR_Playback_t *player = (DVR_Playback_t *) handle;
712 Playback_DeviceVideoParams_t vparams;
713 Playback_DeviceAudioParams_t aparams;
hualing chencc91e1c2020-02-28 13:26:17 +0800714 uint64_t segment_id = player->cur_segment_id;
715 DVR_DEBUG(1, "[%s][%p]segment_id:[%lld]",__func__, handle, segment_id);
hualing chenb31a6c62020-01-13 17:27:00 +0800716
hualing chen040df222020-01-17 13:35:02 +0800717 int sync = DVR_PLAYBACK_SYNC;
hualing chencc91e1c2020-02-28 13:26:17 +0800718 //can used start api to resume playback
719 if (player->cmd.state == DVR_PLAYBACK_STATE_PAUSE) {
720 return dvr_playback_resume(handle);
721 }
hualing chen86e7d482020-01-16 15:13:33 +0800722 player->play_flag = flag;
hualing chen5cbe1a62020-02-10 16:36:36 +0800723 //get segment info and audio video pid fmt ;
hualing chencc91e1c2020-02-28 13:26:17 +0800724 DVR_DEBUG(1, "lock func: %s %p", __func__, handle);
hualing chen86e7d482020-01-16 15:13:33 +0800725 pthread_mutex_lock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +0800726 _dvr_playback_get_playinfo(handle, segment_id, &vparams, &aparams);
hualing chen86e7d482020-01-16 15:13:33 +0800727 //start audio and video
728 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
729 //audio abnd video pis is all invalid, return error.
730 DVR_DEBUG(0, "dvr play back start error, not found audio and video info");
hualing chencc91e1c2020-02-28 13:26:17 +0800731 DVR_DEBUG(1, "unlock func: %s", __func__);
732 pthread_mutex_unlock(&player->lock);
733 DVR_Play_Notify_t notify;
734 memset(&notify, 0 , sizeof(DVR_Play_Notify_t));
735 notify.event = DVR_PLAYBACK_EVENT_TRANSITION_FAILED;
736 notify.info.error_reason = DVR_PLAYBACK_PID_ERROR;
737 notify.info.transition_failed_data.segment_id = segment_id;
738 //get play statue not here
739 _dvr_playback_sent_event(handle, DVR_PLAYBACK_EVENT_TRANSITION_FAILED, &notify);
hualing chen86e7d482020-01-16 15:13:33 +0800740 return -1;
741 }
hualing chenb31a6c62020-01-13 17:27:00 +0800742
hualing chencc91e1c2020-02-28 13:26:17 +0800743 {
hualing chen86e7d482020-01-16 15:13:33 +0800744 if (VALID_PID(vparams.pid)) {
745 player->has_video = DVR_TRUE;
746 playback_device_video_start(player->handle , &vparams);
747 //if set flag is pause live, we need set trick mode
hualing chen5cbe1a62020-02-10 16:36:36 +0800748 if ((player->play_flag&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE) {
hualing chen86e7d482020-01-16 15:13:33 +0800749 playback_device_trick_mode(player->handle, 1);
750 }
hualing chenb31a6c62020-01-13 17:27:00 +0800751 }
hualing chen86e7d482020-01-16 15:13:33 +0800752 if (VALID_PID(aparams.pid)) {
753 player->has_audio = DVR_TRUE;
754 playback_device_audio_start(player->handle , &aparams);
hualing chenb31a6c62020-01-13 17:27:00 +0800755 }
hualing chencc91e1c2020-02-28 13:26:17 +0800756 DVR_DEBUG(1, "player->cmd.cur_cmd:%d", player->cmd.cur_cmd);
757 if (player->cmd.cur_cmd == DVR_PLAYBACK_CMD_FB
758 || player->cmd.cur_cmd == DVR_PLAYBACK_CMD_FF) {
759 player->cmd.state = DVR_PLAYBACK_STATE_START;
760 player->state = DVR_PLAYBACK_STATE_START;
761 if (player->has_video == DVR_TRUE)
762 playback_device_trick_mode(player->handle, 1);
763 DVR_DEBUG(1, "set trick mode ---at start");
764 } else {
765 player->cmd.last_cmd = player->cmd.cur_cmd;
766 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_START;
767 player->cmd.speed.speed.speed = PLAYBACK_SPEED_X1;
768 player->cmd.state = DVR_PLAYBACK_STATE_START;
769 player->state = DVR_PLAYBACK_STATE_START;
770 }
hualing chen86e7d482020-01-16 15:13:33 +0800771 }
hualing chencc91e1c2020-02-28 13:26:17 +0800772 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800773 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +0800774 _start_playback_thread(handle);
hualing chen86e7d482020-01-16 15:13:33 +0800775 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800776}
hualing chen040df222020-01-17 13:35:02 +0800777/**\brief dvr play back add segment info to segment list
hualing chenb31a6c62020-01-13 17:27:00 +0800778 * \param[in] handle playback handle
hualing chen040df222020-01-17 13:35:02 +0800779 * \param[in] info added segment info,con vpid fmt apid fmt.....
hualing chenb31a6c62020-01-13 17:27:00 +0800780 * \retval DVR_SUCCESS On success
781 * \return Error code
782 */
hualing chen040df222020-01-17 13:35:02 +0800783int dvr_playback_add_segment(DVR_PlaybackHandle_t handle, DVR_PlaybackSegmentInfo_t *info) {
784 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800785 DVR_DEBUG(1, "[%s][%p]",__func__, handle);
hualing chenb31a6c62020-01-13 17:27:00 +0800786
hualing chencc91e1c2020-02-28 13:26:17 +0800787 DVR_DEBUG(1, "add segment id: %lld %p", info->segment_id, handle);
hualing chen040df222020-01-17 13:35:02 +0800788 DVR_PlaybackSegmentInfo_t *segment;
hualing chenb31a6c62020-01-13 17:27:00 +0800789
hualing chen040df222020-01-17 13:35:02 +0800790 segment = malloc(sizeof(DVR_PlaybackSegmentInfo_t));
791 memset(segment, 0, sizeof(DVR_PlaybackSegmentInfo_t));
hualing chenb31a6c62020-01-13 17:27:00 +0800792
hualing chen86e7d482020-01-16 15:13:33 +0800793 //not memcpy chun info.
hualing chen040df222020-01-17 13:35:02 +0800794 segment->segment_id = info->segment_id;
hualing chen86e7d482020-01-16 15:13:33 +0800795 //cp location
hualing chen040df222020-01-17 13:35:02 +0800796 memcpy(segment->location, info->location, DVR_MAX_LOCATION_SIZE);
hualing chencc91e1c2020-02-28 13:26:17 +0800797
798 DVR_DEBUG(1, "add location [%s]id[%lld]flag[%x]", segment->location, segment->segment_id, info->flags);
hualing chen040df222020-01-17 13:35:02 +0800799 segment->flags = info->flags;
hualing chen5cbe1a62020-02-10 16:36:36 +0800800
801 //pids
802 if (player->has_pids == DVR_TRUE)
803 memcpy(&segment->pids, &info->pids, sizeof(DVR_PlaybackPids_t));
804
hualing chencc91e1c2020-02-28 13:26:17 +0800805 segment->pids.video.pid = info->pids.video.pid;
806 segment->pids.video.format = info->pids.video.format;
807 segment->pids.video.type = info->pids.video.type;
808
809 segment->pids.audio.pid = info->pids.video.pid;
810 segment->pids.audio.format = info->pids.video.format;
811 segment->pids.audio.type = info->pids.video.type;
812
813 segment->pids.ad.pid = info->pids.video.pid;
814 segment->pids.ad.format = info->pids.video.format;
815 segment->pids.ad.type = info->pids.video.type;
816
817 segment->pids.pcr.pid = info->pids.pcr.pid;
818
819 DVR_DEBUG(1, "lock func: %s pid [0x%x][0x%x][0x%x][0x%x]", __func__,segment->pids.video.pid,segment->pids.audio.pid, info->pids.video.pid,info->pids.audio.pid);
hualing chen86e7d482020-01-16 15:13:33 +0800820 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800821 list_add_tail(&segment->head, &player->segment_list);
hualing chen86e7d482020-01-16 15:13:33 +0800822 pthread_mutex_unlock(&player->lock);
hualing chencc91e1c2020-02-28 13:26:17 +0800823 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chenb31a6c62020-01-13 17:27:00 +0800824
hualing chen5cbe1a62020-02-10 16:36:36 +0800825 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800826}
hualing chen040df222020-01-17 13:35:02 +0800827/**\brief dvr play back remove segment info by segment_id
hualing chenb31a6c62020-01-13 17:27:00 +0800828 * \param[in] handle playback handle
hualing chen040df222020-01-17 13:35:02 +0800829 * \param[in] segment_id need removed segment id
hualing chenb31a6c62020-01-13 17:27:00 +0800830 * \retval DVR_SUCCESS On success
831 * \return Error code
832 */
hualing chen5cbe1a62020-02-10 16:36:36 +0800833int dvr_playback_remove_segment(DVR_PlaybackHandle_t handle, uint64_t segment_id) {
hualing chen040df222020-01-17 13:35:02 +0800834 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen5cbe1a62020-02-10 16:36:36 +0800835 DVR_DEBUG(1, "remove segment id: %lld", segment_id);
hualing chencc91e1c2020-02-28 13:26:17 +0800836 if (segment_id == player->cur_segment_id) {
837 DVR_DEBUG(1, "not suport remove curren segment id: %lld", segment_id);
838 return DVR_FAILURE;
839 }
840 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800841 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800842 DVR_PlaybackSegmentInfo_t *segment;
843 list_for_each_entry(segment, &player->segment_list, head)
hualing chen86e7d482020-01-16 15:13:33 +0800844 {
hualing chen040df222020-01-17 13:35:02 +0800845 if (segment->segment_id == segment_id) {
846 list_del(&segment->head);
847 free(segment);
hualing chen86e7d482020-01-16 15:13:33 +0800848 break;
hualing chenb31a6c62020-01-13 17:27:00 +0800849 }
hualing chen86e7d482020-01-16 15:13:33 +0800850 }
hualing chencc91e1c2020-02-28 13:26:17 +0800851 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800852 pthread_mutex_unlock(&player->lock);
853
854 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800855}
hualing chen040df222020-01-17 13:35:02 +0800856/**\brief dvr play back add segment info
hualing chenb31a6c62020-01-13 17:27:00 +0800857 * \param[in] handle playback handle
hualing chen040df222020-01-17 13:35:02 +0800858 * \param[in] info added segment info,con vpid fmt apid fmt.....
hualing chenb31a6c62020-01-13 17:27:00 +0800859 * \retval DVR_SUCCESS On success
860 * \return Error code
861 */
hualing chen040df222020-01-17 13:35:02 +0800862int dvr_playback_update_segment_flags(DVR_PlaybackHandle_t handle,
hualing chen5cbe1a62020-02-10 16:36:36 +0800863 uint64_t segment_id, DVR_PlaybackSegmentFlag_t flags) {
hualing chen040df222020-01-17 13:35:02 +0800864 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen5cbe1a62020-02-10 16:36:36 +0800865 DVR_DEBUG(1, "update segment id: %lld flag:%d", segment_id, flags);
hualing chenb31a6c62020-01-13 17:27:00 +0800866
hualing chen040df222020-01-17 13:35:02 +0800867 DVR_PlaybackSegmentInfo_t *segment;
hualing chencc91e1c2020-02-28 13:26:17 +0800868 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800869 pthread_mutex_lock(&player->lock);
hualing chen040df222020-01-17 13:35:02 +0800870 list_for_each_entry(segment, &player->segment_list, head)
hualing chen86e7d482020-01-16 15:13:33 +0800871 {
hualing chen040df222020-01-17 13:35:02 +0800872 if (segment->segment_id != segment_id) {
hualing chen86e7d482020-01-16 15:13:33 +0800873 continue;
hualing chenb31a6c62020-01-13 17:27:00 +0800874 }
hualing chen86e7d482020-01-16 15:13:33 +0800875 // if encramble to free, only set flag and return;
876
877 //if displayable to none, we need mute audio and video
hualing chen040df222020-01-17 13:35:02 +0800878 if (segment_id == player->cur_segment_id) {
hualing chen5cbe1a62020-02-10 16:36:36 +0800879 if ((segment->flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == DVR_PLAYBACK_SEGMENT_DISPLAYABLE
880 && (flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == 0) {
hualing chencc91e1c2020-02-28 13:26:17 +0800881 //disable display, mute
hualing chen86e7d482020-01-16 15:13:33 +0800882 playback_device_mute_audio(player->handle, 1);
883 playback_device_mute_video(player->handle, 1);
hualing chen5cbe1a62020-02-10 16:36:36 +0800884 } else if ((segment->flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == 0 &&
885 (flags & DVR_PLAYBACK_SEGMENT_DISPLAYABLE) == DVR_PLAYBACK_SEGMENT_DISPLAYABLE) {
hualing chencc91e1c2020-02-28 13:26:17 +0800886 //enable display, unmute
hualing chen86e7d482020-01-16 15:13:33 +0800887 playback_device_mute_audio(player->handle, 0);
888 playback_device_mute_video(player->handle, 0);
889 } else {
890 //do nothing
891 }
892 } else {
893 //do nothing
894 }
895 //continue , only set flag
hualing chen040df222020-01-17 13:35:02 +0800896 segment->flags = flags;
hualing chen86e7d482020-01-16 15:13:33 +0800897 }
hualing chencc91e1c2020-02-28 13:26:17 +0800898 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800899 pthread_mutex_unlock(&player->lock);
900 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800901}
902
903
hualing chen5cbe1a62020-02-10 16:36:36 +0800904static int _do_check_pid_info(DVR_PlaybackHandle_t handle, DVR_StreamInfo_t now_pid, DVR_StreamInfo_t set_pid, int type) {
hualing chen040df222020-01-17 13:35:02 +0800905 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800906 DVR_DEBUG(1, "do check pid %p", handle);
907 DVR_DEBUG(1, "[%s][%p]",__func__, handle);
hualing chenb31a6c62020-01-13 17:27:00 +0800908
hualing chen86e7d482020-01-16 15:13:33 +0800909 if (now_pid.pid == set_pid.pid) {
910 //do nothing
hualing chenb31a6c62020-01-13 17:27:00 +0800911 return 0;
hualing chen5cbe1a62020-02-10 16:36:36 +0800912 } else if (player->cmd.state == DVR_PLAYBACK_STATE_START) {
hualing chen86e7d482020-01-16 15:13:33 +0800913 if (VALID_PID(now_pid.pid)) {
914 //stop now stream
915 if (type == 0) {
916 //stop vieo
917 playback_device_video_stop(player->handle);
hualing chen5cbe1a62020-02-10 16:36:36 +0800918 player->has_video = DVR_FALSE;
hualing chen86e7d482020-01-16 15:13:33 +0800919 } else if (type == 1) {
920 //stop audio
921 playback_device_audio_stop(player->handle);
hualing chen5cbe1a62020-02-10 16:36:36 +0800922 player->has_audio = DVR_FALSE;
hualing chen86e7d482020-01-16 15:13:33 +0800923 } else if (type == 2) {
924 //stop sub audio
925 playback_device_audio_stop(player->handle);
926 } else if (type == 3) {
927 //pcr
928 }
929 }
930 if (VALID_PID(set_pid.pid)) {
931 //start
932 if (type == 0) {
933 //start vieo
hualing chen040df222020-01-17 13:35:02 +0800934 Playback_DeviceVideoParams_t vparams;
hualing chen86e7d482020-01-16 15:13:33 +0800935 vparams.pid = set_pid.pid;
hualing chen5cbe1a62020-02-10 16:36:36 +0800936 vparams.fmt = _dvr_convert_stream_fmt(set_pid.format, DVR_FALSE);
937 player->has_video = DVR_TRUE;
hualing chencc91e1c2020-02-28 13:26:17 +0800938 playback_device_video_start(player->handle,&vparams);
hualing chen86e7d482020-01-16 15:13:33 +0800939 } else if (type == 1) {
940 //start audio
hualing chen040df222020-01-17 13:35:02 +0800941 Playback_DeviceAudioParams_t aparams;
hualing chen86e7d482020-01-16 15:13:33 +0800942 aparams.pid = set_pid.pid;
hualing chen5cbe1a62020-02-10 16:36:36 +0800943 aparams.fmt = _dvr_convert_stream_fmt(set_pid.format, DVR_TRUE);
944 player->has_audio = DVR_TRUE;
hualing chencc91e1c2020-02-28 13:26:17 +0800945 playback_device_audio_start(player->handle,&aparams);
hualing chen86e7d482020-01-16 15:13:33 +0800946 } else if (type == 2) {
947 //start sub audio
hualing chen040df222020-01-17 13:35:02 +0800948 Playback_DeviceAudioParams_t aparams;
hualing chen86e7d482020-01-16 15:13:33 +0800949 aparams.pid = set_pid.pid;
hualing chen5cbe1a62020-02-10 16:36:36 +0800950 aparams.fmt = _dvr_convert_stream_fmt(set_pid.format, DVR_TRUE);
951 player->has_audio = DVR_TRUE;
hualing chencc91e1c2020-02-28 13:26:17 +0800952 playback_device_audio_start(player->handle, &aparams);
hualing chen86e7d482020-01-16 15:13:33 +0800953 } else if (type == 3) {
954 //pcr
955 }
hualing chen5cbe1a62020-02-10 16:36:36 +0800956 //audio and video all close
957 if (!player->has_audio && !player->has_video) {
958 player->state = DVR_PLAYBACK_STATE_STOP;
959 }
hualing chen86e7d482020-01-16 15:13:33 +0800960 }
961 }
962 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800963}
hualing chen5cbe1a62020-02-10 16:36:36 +0800964/**\brief dvr play back update segment pids
965 * if updated segment is ongoing segment, we need start new
hualing chenb31a6c62020-01-13 17:27:00 +0800966 * add pid stream and stop remove pid stream.
967 * \param[in] handle playback handle
hualing chen5cbe1a62020-02-10 16:36:36 +0800968 * \param[in] segment_id need updated pids segment id
hualing chenb31a6c62020-01-13 17:27:00 +0800969 * \retval DVR_SUCCESS On success
970 * \return Error code
971 */
hualing chen5cbe1a62020-02-10 16:36:36 +0800972int dvr_playback_update_segment_pids(DVR_PlaybackHandle_t handle, uint64_t segment_id, DVR_PlaybackPids_t *p_pids) {
hualing chen040df222020-01-17 13:35:02 +0800973 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +0800974 DVR_DEBUG(1, "update segment id: %lld", segment_id);
975 DVR_DEBUG(1, "[%s][%p]",__func__, handle);
hualing chenb31a6c62020-01-13 17:27:00 +0800976
hualing chen040df222020-01-17 13:35:02 +0800977 DVR_PlaybackSegmentInfo_t *segment;
hualing chencc91e1c2020-02-28 13:26:17 +0800978 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +0800979 pthread_mutex_lock(&player->lock);
hualing chencc91e1c2020-02-28 13:26:17 +0800980 DVR_DEBUG(1, "get lock [%p] update segment id: %lld cur id %lld",handle, segment_id, player->cur_segment_id);
981
hualing chen040df222020-01-17 13:35:02 +0800982 list_for_each_entry(segment, &player->segment_list, head)
hualing chen86e7d482020-01-16 15:13:33 +0800983 {
hualing chen040df222020-01-17 13:35:02 +0800984 if (segment->segment_id == segment_id) {
hualing chen5cbe1a62020-02-10 16:36:36 +0800985
986 if (player->cur_segment_id == segment_id) {
987 if (player->cmd.state == DVR_PLAYBACK_STATE_FF
988 || player->cmd.state == DVR_PLAYBACK_STATE_FF) {
989 //do nothing when ff fb
990 DVR_DEBUG(1, "now is ff fb, not to update cur segment info\r\n");
hualing chencc91e1c2020-02-28 13:26:17 +0800991 DVR_DEBUG(1, "unlock func: %s", __func__);
992 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +0800993 return 0;
994 }
995
996 //if segment is on going segment,we need stop start stream
997 if (player->cmd.state == DVR_PLAYBACK_STATE_START) {
hualing chencc91e1c2020-02-28 13:26:17 +0800998 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +0800999 //check video pids, stop or restart
hualing chencc91e1c2020-02-28 13:26:17 +08001000 _do_check_pid_info((DVR_PlaybackHandle_t)player, segment->pids.video, p_pids->video, 0);
hualing chen5cbe1a62020-02-10 16:36:36 +08001001 //check audio pids stop or restart
hualing chencc91e1c2020-02-28 13:26:17 +08001002 _do_check_pid_info((DVR_PlaybackHandle_t)player, segment->pids.audio, p_pids->audio, 1);
hualing chen5cbe1a62020-02-10 16:36:36 +08001003 //check sub audio pids stop or restart
hualing chencc91e1c2020-02-28 13:26:17 +08001004 _do_check_pid_info((DVR_PlaybackHandle_t)player, segment->pids.ad, p_pids->ad, 2);
hualing chen5cbe1a62020-02-10 16:36:36 +08001005 //check pcr pids stop or restart
hualing chencc91e1c2020-02-28 13:26:17 +08001006 _do_check_pid_info((DVR_PlaybackHandle_t)player, segment->pids.pcr, p_pids->pcr, 3);
1007 pthread_mutex_lock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001008 } else if (player->cmd.state == DVR_PLAYBACK_STATE_PAUSE) {
1009 //if state is pause, we need process at resume api. we only record change info
1010 int v_cmd = DVR_PLAYBACK_CMD_NONE;
1011 int a_cmd = DVR_PLAYBACK_CMD_NONE;
1012 if (VALID_PID(segment->pids.video.pid)
1013 && VALID_PID(p_pids->video.pid)
1014 && segment->pids.video.pid != p_pids->video.pid) {
1015 //restart video
1016 v_cmd = DVR_PLAYBACK_CMD_VRESTART;
1017 }
1018 if (!VALID_PID(segment->pids.video.pid)
1019 && VALID_PID(p_pids->video.pid)
1020 && segment->pids.video.pid != p_pids->video.pid) {
1021 //start video
1022 v_cmd = DVR_PLAYBACK_CMD_VSTART;
1023 }
1024 if (VALID_PID(segment->pids.video.pid)
1025 && !VALID_PID(p_pids->video.pid)
1026 && segment->pids.video.pid != p_pids->video.pid) {
1027 //stop video
1028 v_cmd = DVR_PLAYBACK_CMD_VSTOP;
1029 }
1030 if (VALID_PID(segment->pids.audio.pid)
1031 && VALID_PID(p_pids->audio.pid)
1032 && segment->pids.audio.pid != p_pids->audio.pid) {
1033 //restart audio
1034 a_cmd = DVR_PLAYBACK_CMD_ARESTART;
1035 }
1036 if (!VALID_PID(segment->pids.audio.pid)
1037 && VALID_PID(p_pids->audio.pid)
1038 && segment->pids.audio.pid != p_pids->audio.pid) {
1039 //start audio
1040 a_cmd = DVR_PLAYBACK_CMD_ASTART;
1041 }
1042 if (VALID_PID(segment->pids.audio.pid)
1043 && !VALID_PID(p_pids->audio.pid)
1044 && segment->pids.audio.pid != p_pids->audio.pid) {
1045 //stop audio
1046 a_cmd = DVR_PLAYBACK_CMD_ASTOP;
1047 }
1048 if (a_cmd == DVR_PLAYBACK_CMD_NONE
1049 && v_cmd == DVR_PLAYBACK_CMD_NONE) {
1050 //do nothing
1051 } else if (a_cmd == DVR_PLAYBACK_CMD_NONE
1052 || v_cmd == DVR_PLAYBACK_CMD_NONE) {
1053 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1054 player->cmd.cur_cmd = a_cmd != DVR_PLAYBACK_CMD_NONE ? a_cmd : v_cmd;
1055 } else if (a_cmd != DVR_PLAYBACK_CMD_NONE
1056 && v_cmd != DVR_PLAYBACK_CMD_NONE) {
1057 if (v_cmd == DVR_PLAYBACK_CMD_VRESTART
1058 && (a_cmd == DVR_PLAYBACK_CMD_ARESTART)) {
1059 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1060 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_AVRESTART;
1061 }else if (v_cmd == DVR_PLAYBACK_CMD_VRESTART
1062 && a_cmd == DVR_PLAYBACK_CMD_ASTART) {
1063 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1064 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_ASTARTVRESTART;
1065 } else {
1066 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1067 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_ASTOPVRESTART;
1068 }
1069
1070 if (v_cmd == DVR_PLAYBACK_CMD_VSTART
1071 && (a_cmd == DVR_PLAYBACK_CMD_ARESTART)) {
1072 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1073 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_VSTARTARESTART;
1074 } else if (v_cmd == DVR_PLAYBACK_CMD_VSTART
1075 && a_cmd == DVR_PLAYBACK_CMD_ASTART) {
1076 //not occur this case
1077 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1078 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_START;
1079 } else {
1080 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1081 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_ASTOPVSTART;
1082 }
1083
1084 if (v_cmd == DVR_PLAYBACK_CMD_VSTOP
1085 && a_cmd == DVR_PLAYBACK_CMD_ASTART) {
1086 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1087 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_VSTOPASTART;
1088 } else if (v_cmd == DVR_PLAYBACK_CMD_VSTOP
1089 && a_cmd == DVR_PLAYBACK_CMD_ARESTART) {
1090 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1091 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_VSTOPARESTART;
1092 } else {
1093 //not occur this case
1094 player->cmd.last_cmd =DVR_PLAYBACK_CMD_PAUSE;
1095 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_STOP;
1096 }
1097 }
1098 }
1099 }
hualing chen86e7d482020-01-16 15:13:33 +08001100 //save pids info
hualing chen040df222020-01-17 13:35:02 +08001101 memcpy(&segment->pids, p_pids, sizeof(DVR_PlaybackPids_t));
hualing chen86e7d482020-01-16 15:13:33 +08001102 break;
hualing chenb31a6c62020-01-13 17:27:00 +08001103 }
hualing chen86e7d482020-01-16 15:13:33 +08001104 }
hualing chencc91e1c2020-02-28 13:26:17 +08001105 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001106 pthread_mutex_unlock(&player->lock);
1107 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +08001108}
1109/**\brief Stop play, will stop video and audio
1110 * \param[in] handle playback handle
1111 * \param[in] clear is clear last frame
1112 * \retval DVR_SUCCESS On success
1113 * \return Error code
1114 */
hualing chen040df222020-01-17 13:35:02 +08001115int dvr_playback_stop(DVR_PlaybackHandle_t handle, DVR_Bool_t clear) {
1116 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001117 DVR_DEBUG(1, "---into-stop-----");
1118 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001119 pthread_mutex_lock(&player->lock);
hualing chencc91e1c2020-02-28 13:26:17 +08001120 DVR_DEBUG(1, "---into-stop---1--");
1121
hualing chen86e7d482020-01-16 15:13:33 +08001122 playback_device_video_stop(player->handle);
1123 playback_device_audio_stop(player->handle);
1124 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001125 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_STOP;
1126 player->cmd.state = DVR_PLAYBACK_STATE_STOP;
1127 player->state = DVR_PLAYBACK_STATE_STOP;
hualing chencc91e1c2020-02-28 13:26:17 +08001128 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001129 pthread_mutex_unlock(&player->lock);
1130 //destory thread
1131 _stop_playback_thread(handle);
1132 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +08001133}
1134/**\brief Start play audio
1135 * \param[in] handle playback handle
1136 * \param[in] params audio playback params,contains fmt and pid...
1137 * \retval DVR_SUCCESS On success
1138 * \return Error code
1139 */
hualing chen040df222020-01-17 13:35:02 +08001140int dvr_playback_audio_start(DVR_PlaybackHandle_t handle, Playback_DeviceAudioParams_t *param) {
1141 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001142 DVR_DEBUG(1, "into func: %s", __func__);
1143 DVR_DEBUG(1, "[%s][%p]",__func__, handle);
hualing chen86e7d482020-01-16 15:13:33 +08001144 _start_playback_thread(handle);
1145 //start audio and video
hualing chencc91e1c2020-02-28 13:26:17 +08001146 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001147 pthread_mutex_lock(&player->lock);
1148 player->has_audio = DVR_TRUE;
hualing chen5cbe1a62020-02-10 16:36:36 +08001149 playback_device_audio_start(player->handle , param);
hualing chen86e7d482020-01-16 15:13:33 +08001150 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001151 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_ASTART;
1152 player->cmd.state = DVR_PLAYBACK_STATE_START;
1153 player->state = DVR_PLAYBACK_STATE_START;
hualing chencc91e1c2020-02-28 13:26:17 +08001154 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001155 pthread_mutex_unlock(&player->lock);
1156 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +08001157}
1158/**\brief Stop play audio
1159 * \param[in] handle playback handle
1160 * \retval DVR_SUCCESS On success
1161 * \return Error code
1162 */
hualing chen040df222020-01-17 13:35:02 +08001163int dvr_playback_audio_stop(DVR_PlaybackHandle_t handle) {
1164 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001165 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001166 pthread_mutex_lock(&player->lock);
1167 player->has_audio = DVR_FALSE;
1168 playback_device_audio_stop(player->handle);
1169
1170 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001171 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_ASTOP;
hualing chen86e7d482020-01-16 15:13:33 +08001172
1173 if (player->has_video == DVR_FALSE) {
hualing chen040df222020-01-17 13:35:02 +08001174 player->cmd.state = DVR_PLAYBACK_STATE_STOP;
1175 player->state = DVR_PLAYBACK_STATE_STOP;
hualing chen86e7d482020-01-16 15:13:33 +08001176 //destory thread
1177 _stop_playback_thread(handle);
1178 } else {
1179 //do nothing.video is playing
1180 }
hualing chencc91e1c2020-02-28 13:26:17 +08001181 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001182 pthread_mutex_unlock(&player->lock);
1183 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +08001184}
1185/**\brief Start play video
1186 * \param[in] handle playback handle
1187 * \param[in] params video playback params,contains fmt and pid...
1188 * \retval DVR_SUCCESS On success
1189 * \return Error code
1190 */
hualing chen040df222020-01-17 13:35:02 +08001191int dvr_playback_video_start(DVR_PlaybackHandle_t handle, Playback_DeviceVideoParams_t *param) {
1192 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chen86e7d482020-01-16 15:13:33 +08001193 _start_playback_thread(handle);
1194 //start audio and video
hualing chencc91e1c2020-02-28 13:26:17 +08001195 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001196 pthread_mutex_lock(&player->lock);
1197 player->has_video = DVR_TRUE;
1198 playback_device_video_start(player->handle , param);
1199 //if set flag is pause live, we need set trick mode
hualing chen5cbe1a62020-02-10 16:36:36 +08001200 if ((player->play_flag&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE) {
hualing chen86e7d482020-01-16 15:13:33 +08001201 playback_device_trick_mode(player->handle, 1);
1202 }
1203 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001204 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_VSTART;
1205 player->cmd.state = DVR_PLAYBACK_STATE_START;
1206 player->state = DVR_PLAYBACK_STATE_START;
hualing chencc91e1c2020-02-28 13:26:17 +08001207 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001208 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +08001209 return DVR_SUCCESS;
1210}
1211/**\brief Stop play video
1212 * \param[in] handle playback handle
1213 * \retval DVR_SUCCESS On success
1214 * \return Error code
1215 */
hualing chen040df222020-01-17 13:35:02 +08001216int dvr_playback_video_stop(DVR_PlaybackHandle_t handle) {
1217 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001218 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001219 pthread_mutex_lock(&player->lock);
1220 player->has_video = DVR_FALSE;
hualing chenb31a6c62020-01-13 17:27:00 +08001221 playback_device_video_stop(player->handle);
hualing chen86e7d482020-01-16 15:13:33 +08001222
1223 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001224 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_VSTOP;
hualing chen86e7d482020-01-16 15:13:33 +08001225
1226 if (player->has_audio == DVR_FALSE) {
hualing chen040df222020-01-17 13:35:02 +08001227 player->cmd.state = DVR_PLAYBACK_STATE_STOP;
1228 player->state = DVR_PLAYBACK_STATE_STOP;
hualing chen86e7d482020-01-16 15:13:33 +08001229 //destory thread
1230 _stop_playback_thread(handle);
1231 } else {
1232 //do nothing.audio is playing
1233 }
hualing chencc91e1c2020-02-28 13:26:17 +08001234 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001235 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +08001236 return DVR_SUCCESS;
1237}
1238/**\brief Pause play
1239 * \param[in] handle playback handle
1240 * \param[in] flush whether its internal buffers should be flushed
1241 * \retval DVR_SUCCESS On success
1242 * \return Error code
1243 */
hualing chen040df222020-01-17 13:35:02 +08001244int dvr_playback_pause(DVR_PlaybackHandle_t handle, DVR_Bool_t flush) {
1245 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001246 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001247 pthread_mutex_lock(&player->lock);
1248 playback_device_pause(player->handle);
1249 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001250 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_PAUSE;
1251 player->cmd.state = DVR_PLAYBACK_STATE_PAUSE;
1252 player->state = DVR_PLAYBACK_STATE_PAUSE;
hualing chencc91e1c2020-02-28 13:26:17 +08001253 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001254 pthread_mutex_unlock(&player->lock);
1255 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +08001256}
1257
hualing chen5cbe1a62020-02-10 16:36:36 +08001258//not add lock
1259static int _dvr_cmd(DVR_PlaybackHandle_t handle, int cmd)
1260{
1261 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1262
1263 //get video params and audio params
hualing chencc91e1c2020-02-28 13:26:17 +08001264 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001265 pthread_mutex_lock(&player->lock);
1266 Playback_DeviceVideoParams_t vparams;
1267 Playback_DeviceAudioParams_t aparams;
hualing chencc91e1c2020-02-28 13:26:17 +08001268 uint64_t segmentid = player->cur_segment_id;
hualing chen5cbe1a62020-02-10 16:36:36 +08001269
1270 _dvr_playback_get_playinfo(handle, segmentid, &vparams, &aparams);
hualing chencc91e1c2020-02-28 13:26:17 +08001271 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001272 pthread_mutex_unlock(&player->lock);
1273
1274 switch (cmd) {
1275 case DVR_PLAYBACK_CMD_AVRESTART:
1276 //av restart
1277 dvr_playback_video_stop(player->handle);
1278 dvr_playback_audio_stop(player->handle);
1279 dvr_playback_video_start(player->handle, &vparams);
1280 dvr_playback_audio_start(player->handle, &aparams);
1281 break;
1282 case DVR_PLAYBACK_CMD_VRESTART:
1283 dvr_playback_video_stop(player->handle);
1284 dvr_playback_video_start(player->handle, &vparams);
1285 break;
1286 case DVR_PLAYBACK_CMD_VSTART:
1287 dvr_playback_video_start(player->handle, &vparams);
1288 break;
1289 case DVR_PLAYBACK_CMD_VSTOP:
1290 dvr_playback_video_stop(player->handle);
1291 break;
1292 case DVR_PLAYBACK_CMD_ARESTART:
1293 //a restart
1294 dvr_playback_audio_stop(player->handle);
1295 dvr_playback_audio_start(player->handle, &aparams);
1296 break;
1297 case DVR_PLAYBACK_CMD_ASTART:
1298 dvr_playback_audio_start(player->handle, &aparams);
1299 break;
1300 case DVR_PLAYBACK_CMD_ASTOP:
1301 dvr_playback_audio_stop(player->handle);
1302 break;
1303 case DVR_PLAYBACK_CMD_ASTOPVRESTART:
1304 dvr_playback_audio_stop(player->handle);
1305 dvr_playback_video_stop(player->handle);
1306 dvr_playback_video_start(player->handle, &vparams);
1307 break;
1308 case DVR_PLAYBACK_CMD_ASTOPVSTART:
1309 dvr_playback_audio_stop(player->handle);
1310 dvr_playback_video_start(player->handle, &vparams);
1311 break;
1312 case DVR_PLAYBACK_CMD_VSTOPARESTART:
1313 dvr_playback_video_stop(player->handle);
1314 dvr_playback_audio_stop(player->handle);
1315 dvr_playback_audio_start(player->handle, &aparams);
1316 break;
1317 case DVR_PLAYBACK_CMD_STOP:
1318 break;
1319 case DVR_PLAYBACK_CMD_START:
1320 break;
1321 case DVR_PLAYBACK_CMD_ASTARTVRESTART:
1322 dvr_playback_video_stop(player->handle);
1323 dvr_playback_video_start(player->handle, &vparams);
1324 dvr_playback_audio_start(player->handle, &aparams);
1325 break;
1326 case DVR_PLAYBACK_CMD_VSTARTARESTART:
1327 dvr_playback_audio_stop(player->handle);
1328 dvr_playback_video_start(player->handle, &vparams);
1329 dvr_playback_audio_start(player->handle, &aparams);
1330 break;
1331 case DVR_PLAYBACK_CMD_FF:
1332 case DVR_PLAYBACK_CMD_FB:
1333 _dvr_playback_fffb(player->handle);
1334 break;
1335 default:
1336 break;
1337 }
1338 return DVR_SUCCESS;
1339}
1340
1341/**\brief Resume play
hualing chenb31a6c62020-01-13 17:27:00 +08001342 * \param[in] handle playback handle
hualing chenb31a6c62020-01-13 17:27:00 +08001343 * \retval DVR_SUCCESS On success
1344 * \return Error code
1345 */
hualing chen5cbe1a62020-02-10 16:36:36 +08001346int dvr_playback_resume(DVR_PlaybackHandle_t handle) {
1347 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1348
1349 if (player->cmd.cur_cmd == DVR_PLAYBACK_CMD_PAUSE) {
hualing chencc91e1c2020-02-28 13:26:17 +08001350 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001351 pthread_mutex_lock(&player->lock);
1352 playback_device_resume(player->handle);
1353 player->cmd.last_cmd = player->cmd.cur_cmd;
1354 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_RESUME;
1355 player->cmd.state = DVR_PLAYBACK_STATE_START;
1356 player->state = DVR_PLAYBACK_STATE_START;
hualing chencc91e1c2020-02-28 13:26:17 +08001357 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001358 pthread_mutex_unlock(&player->lock);
1359 } else {
1360 //player->cmd.last_cmd = DVR_PLAYBACK_CMD_RESUME;
1361 _dvr_cmd(handle, player->cmd.cur_cmd);
1362 }
1363 return DVR_SUCCESS;
1364}
1365
1366
1367/**\brief seek
1368 * \param[in] handle playback handle
1369 * \param[in] time_offset time offset base cur segment
1370 * \retval DVR_SUCCESS On success
1371 * \return Error code
1372 */
hualing chencc91e1c2020-02-28 13:26:17 +08001373int dvr_playback_seek(DVR_PlaybackHandle_t handle, uint64_t segment_id, uint32_t time_offset) {
hualing chen040df222020-01-17 13:35:02 +08001374 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001375 DVR_DEBUG(1, "lock func: %s segment_id %llu time_offset %u", __func__, segment_id, (uint32_t)time_offset);
1376 DVR_DEBUG(1, "[%s][%p]---player->state[%d]----",__func__, handle, player->state);
hualing chen86e7d482020-01-16 15:13:33 +08001377 pthread_mutex_lock(&player->lock);
hualing chencc91e1c2020-02-28 13:26:17 +08001378 _dvr_get_cur_time(handle);
1379 _dvr_get_end_time(handle);
1380
hualing chen86e7d482020-01-16 15:13:33 +08001381 int offset = -1;
hualing chen5cbe1a62020-02-10 16:36:36 +08001382 //open segment if id is not current segment
1383 _dvr_open_segment(handle, segment_id);
hualing chencc91e1c2020-02-28 13:26:17 +08001384 DVR_DEBUG(1, "seek open id[%lld]flag[0x%x] time_offset %u", player->cur_segment.segment_id, player->cur_segment.flags, time_offset);
hualing chen86e7d482020-01-16 15:13:33 +08001385 //get file offset by time
hualing chencc91e1c2020-02-28 13:26:17 +08001386 offset = segment_seek(player->r_handle, (uint64_t)time_offset);
1387 DVR_DEBUG(0, "seek get offset by time offset, offset=%d time_offset %u",offset, time_offset);
hualing chen86e7d482020-01-16 15:13:33 +08001388 //seek file
hualing chen86e7d482020-01-16 15:13:33 +08001389 if (offset == -1) {
1390 //seek 2M data once for test
1391 //seek error
1392 offset = player->offset + (2*1014*1024);
1393 }
1394 player->offset = offset;
hualing chencc91e1c2020-02-28 13:26:17 +08001395
hualing chen5cbe1a62020-02-10 16:36:36 +08001396 if (player->state == DVR_PLAYBACK_STATE_STOP) {
1397 //only seek file,not start
hualing chencc91e1c2020-02-28 13:26:17 +08001398 DVR_DEBUG(1, "unlock func: %s", __func__);
1399 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001400 return 0;
1401 }
hualing chen86e7d482020-01-16 15:13:33 +08001402 //stop play
1403 DVR_DEBUG(0, "seek stop play, not inject data");
1404 if (player->has_video)
hualing chenb31a6c62020-01-13 17:27:00 +08001405 playback_device_video_stop(player->handle);
hualing chencc91e1c2020-02-28 13:26:17 +08001406 if (player->has_audio)
hualing chenb31a6c62020-01-13 17:27:00 +08001407 playback_device_audio_stop(player->handle);
hualing chen86e7d482020-01-16 15:13:33 +08001408 //start play
hualing chen040df222020-01-17 13:35:02 +08001409 Playback_DeviceVideoParams_t vparams;
1410 Playback_DeviceAudioParams_t aparams;
hualing chenb31a6c62020-01-13 17:27:00 +08001411
hualing chen040df222020-01-17 13:35:02 +08001412 player->cur_segment_id = segment_id;
1413
1414 int sync = DVR_PLAYBACK_SYNC;
hualing chen5cbe1a62020-02-10 16:36:36 +08001415 //get segment info and audio video pid fmt ;
1416 _dvr_playback_get_playinfo(handle, segment_id, &vparams, &aparams);
hualing chen86e7d482020-01-16 15:13:33 +08001417 //start audio and video
1418 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
1419 //audio abnd video pis is all invalid, return error.
1420 DVR_DEBUG(0, "seek start dvr play back start error, not found audio and video info");
hualing chencc91e1c2020-02-28 13:26:17 +08001421 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001422 pthread_mutex_unlock(&player->lock);
1423 return -1;
1424 }
1425 //add
hualing chen040df222020-01-17 13:35:02 +08001426 if (sync == DVR_PLAYBACK_SYNC) {
hualing chen86e7d482020-01-16 15:13:33 +08001427 if (VALID_PID(vparams.pid)) {
hualing chen5cbe1a62020-02-10 16:36:36 +08001428 //player->has_video;
hualing chen86e7d482020-01-16 15:13:33 +08001429 playback_device_video_start(player->handle , &vparams);
hualing chen5cbe1a62020-02-10 16:36:36 +08001430 if (player->cmd.cur_cmd == DVR_PLAYBACK_CMD_PAUSE) {
1431 //if is pause state. we need set trick mode.
hualing chencc91e1c2020-02-28 13:26:17 +08001432 DVR_DEBUG(1, "seek set trick mode", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001433 playback_device_trick_mode(player->handle, 1);
1434 }
hualing chenb31a6c62020-01-13 17:27:00 +08001435 }
hualing chen86e7d482020-01-16 15:13:33 +08001436 if (VALID_PID(aparams.pid)) {
hualing chen5cbe1a62020-02-10 16:36:36 +08001437 //player->has_video;
hualing chen86e7d482020-01-16 15:13:33 +08001438 playback_device_audio_start(player->handle , &aparams);
hualing chenb31a6c62020-01-13 17:27:00 +08001439 }
hualing chen86e7d482020-01-16 15:13:33 +08001440 }
hualing chen5cbe1a62020-02-10 16:36:36 +08001441
hualing chen86e7d482020-01-16 15:13:33 +08001442 player->cmd.last_cmd = player->cmd.cur_cmd;
hualing chen040df222020-01-17 13:35:02 +08001443 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_SEEK;
1444 player->cmd.state = DVR_PLAYBACK_STATE_START;
1445 player->state = DVR_PLAYBACK_STATE_START;
hualing chencc91e1c2020-02-28 13:26:17 +08001446 DVR_DEBUG(1, "unlock func: %s ---", __func__);
hualing chen86e7d482020-01-16 15:13:33 +08001447 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +08001448
1449 return DVR_SUCCESS;
1450}
hualing chen5cbe1a62020-02-10 16:36:36 +08001451
1452//get current segment current pcr time of read pos
1453static int _dvr_get_cur_time(DVR_PlaybackHandle_t handle) {
1454 //get cur time of segment
1455 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001456 int cache = 500;//defalut es buf cache 500ms
1457 uint32_t cur = segment_tell_current_time(player->r_handle);
1458 return cur > cache ? cur - cache : cur;
1459}
1460
1461//get current segment current pcr time of read pos
1462static int _dvr_get_end_time(DVR_PlaybackHandle_t handle) {
1463 //get cur time of segment
1464 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1465 //if (player->openParams.is_timeshift == DVR_TRUE) {
1466 //get dur real time
1467 return segment_tell_total_time(player->r_handle);
1468 //}
1469 //return player->dur;
hualing chen5cbe1a62020-02-10 16:36:36 +08001470}
1471
1472//start replay
1473static int _dvr_playback_calculate_seekpos(DVR_PlaybackHandle_t handle) {
1474
1475 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1476 //calculate pcr seek time
1477 int t_diff = 0;
1478 int seek_time = 0;
1479 if (player->fffb_start == -1) {
1480 //set fffb start time ms
1481 player->fffb_start = _dvr_time_getClock();
1482 player->fffb_current = player->fffb_start;
1483 //get segment current time pos
1484 player->fffb_start_pcr = _dvr_get_cur_time(handle);
1485 t_diff = 0;
1486 } else {
1487 player->fffb_current = _dvr_time_getClock();
1488 t_diff = player->fffb_current - player->fffb_start;
1489 seek_time = player->fffb_start_pcr + t_diff *player->speed;
1490 //seek segment pos
1491 if (player->r_handle) {
1492 segment_seek(player->r_handle, seek_time);
1493 } else {
1494 //
1495 DVR_DEBUG(1, "segment not open,can not seek");
1496 }
1497 }
1498 return 0;
1499}
1500
1501
1502//start replay
1503static int _dvr_playback_fffb_replay(DVR_PlaybackHandle_t handle) {
1504 //
1505 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1506 //stop
1507 if (player->has_video)
1508 playback_device_video_stop(player->handle);
1509 if (player->has_audio)
1510 playback_device_audio_stop(player->handle);
1511 //start video and audio
1512
1513 Playback_DeviceVideoParams_t vparams;
1514 Playback_DeviceAudioParams_t aparams;
1515 uint64_t segment_id = 0;
1516
1517 //get segment info and audio video pid fmt ;
hualing chencc91e1c2020-02-28 13:26:17 +08001518 //pthread_mutex_lock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001519 _dvr_playback_get_playinfo(handle, segment_id, &vparams, &aparams);
1520 //start audio and video
1521 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
1522 //audio abnd video pis is all invalid, return error.
1523 DVR_DEBUG(0, "dvr play back restart error, not found audio and video info");
hualing chencc91e1c2020-02-28 13:26:17 +08001524 //pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001525 return -1;
1526 }
1527
1528 if (VALID_PID(vparams.pid)) {
1529 player->has_video = DVR_TRUE;
1530 playback_device_video_start(player->handle , &vparams);
1531 //if set flag is pause live, we need set trick mode
1532 playback_device_trick_mode(player->handle, 1);
1533 }
1534 if (VALID_PID(aparams.pid)) {
1535 player->has_audio = DVR_TRUE;
1536 playback_device_audio_start(player->handle , &aparams);
1537 }
1538
hualing chencc91e1c2020-02-28 13:26:17 +08001539 //pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001540 return 0;
1541}
1542
1543static int _dvr_playback_fffb(DVR_PlaybackHandle_t handle) {
1544 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1545 if (_dvr_time_getClock() < player->fffb_current + FFFB_SLEEP_TIME)
1546 return 0;
hualing chencc91e1c2020-02-28 13:26:17 +08001547 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001548 pthread_mutex_lock(&player->lock);
1549
1550 _dvr_playback_calculate_seekpos(handle);
1551 _dvr_playback_fffb_replay(handle);
hualing chencc91e1c2020-02-28 13:26:17 +08001552 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001553
1554 pthread_mutex_unlock(&player->lock);
1555 return DVR_SUCCESS;
1556}
1557
1558//start replay
1559static int _dvr_playback_replay(DVR_PlaybackHandle_t handle) {
1560 //
1561 DVR_Playback_t *player = (DVR_Playback_t *) handle;
1562 //stop
1563 if (player->has_video)
1564 playback_device_video_stop(player->handle);
1565 if (player->has_audio)
1566 playback_device_audio_stop(player->handle);
1567 //start video and audio
1568
1569 Playback_DeviceVideoParams_t vparams;
1570 Playback_DeviceAudioParams_t aparams;
hualing chencc91e1c2020-02-28 13:26:17 +08001571 uint64_t segment_id = 0LL;
hualing chen5cbe1a62020-02-10 16:36:36 +08001572
1573 //get segment info and audio video pid fmt ;
hualing chencc91e1c2020-02-28 13:26:17 +08001574 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001575 pthread_mutex_lock(&player->lock);
1576 _dvr_playback_get_playinfo(handle, segment_id, &vparams, &aparams);
1577 //start audio and video
1578 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
1579 //audio abnd video pis is all invalid, return error.
1580 DVR_DEBUG(0, "dvr play back restart error, not found audio and video info");
hualing chencc91e1c2020-02-28 13:26:17 +08001581 DVR_DEBUG(1, "unlock func: %s", __func__);
1582 pthread_mutex_unlock(&player->lock);
hualing chen5cbe1a62020-02-10 16:36:36 +08001583 return -1;
1584 }
1585
1586 if (VALID_PID(vparams.pid)) {
1587 player->has_video = DVR_TRUE;
1588 playback_device_video_start(player->handle , &vparams);
1589 //if set flag is pause live, we need set trick mode
1590 playback_device_trick_mode(player->handle, 1);
1591 }
1592 if (VALID_PID(aparams.pid)) {
1593 player->has_audio = DVR_TRUE;
1594 playback_device_audio_start(player->handle , &aparams);
1595 }
hualing chencc91e1c2020-02-28 13:26:17 +08001596 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001597
1598 pthread_mutex_unlock(&player->lock);
1599 return 0;
1600}
1601
1602
hualing chenb31a6c62020-01-13 17:27:00 +08001603/**\brief Set play speed
1604 * \param[in] handle playback handle
1605 * \param[in] speed playback speed
1606 * \retval DVR_SUCCESS On success
1607 * \return Error code
1608 */
hualing chen5cbe1a62020-02-10 16:36:36 +08001609int dvr_playback_set_speed(DVR_PlaybackHandle_t handle, DVR_PlaybackSpeed_t speed) {
1610
1611 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001612 DVR_DEBUG(1, "lock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001613 pthread_mutex_lock(&player->lock);
1614 if (player->cmd.cur_cmd != DVR_PLAYBACK_CMD_FF
1615 && player->cmd.cur_cmd != DVR_PLAYBACK_CMD_FB) {
1616 player->cmd.last_cmd = player->cmd.cur_cmd;
1617 }
1618 //only set mode and speed info, we will deal ff fb at playback thread.
1619 player->cmd.speed.mode = speed.mode;
1620 player->cmd.speed.speed = speed.speed;
1621 if (speed.mode == DVR_PLAYBACK_FAST_FORWARD)
1622 player->speed = speed.speed.speed/100;
1623 else
1624 player->speed = -speed.speed.speed/100;
1625
1626 if (speed.mode == DVR_PLAYBACK_FAST_FORWARD)
1627 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_FF;
1628 else
1629 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_FB;
1630 //need exit ff fb
1631 if (speed.speed.speed == PLAYBACK_SPEED_X1) {
1632 player->cmd.cur_cmd = DVR_PLAYBACK_CMD_AVRESTART;
1633 }
hualing chencc91e1c2020-02-28 13:26:17 +08001634 DVR_DEBUG(1, "unlock func: %s", __func__);
hualing chen5cbe1a62020-02-10 16:36:36 +08001635 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +08001636
1637 return DVR_SUCCESS;
1638}
1639/**\brief Get playback status
1640 * \param[in] handle playback handle
1641 * \param[out] p_status playback status
1642 * \retval DVR_SUCCESS On success
1643 * \return Error code
1644 */
hualing chen040df222020-01-17 13:35:02 +08001645int dvr_playback_get_status(DVR_PlaybackHandle_t handle,
hualing chen5cbe1a62020-02-10 16:36:36 +08001646 DVR_PlaybackStatus_t *p_status) {
1647//
1648 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chencc91e1c2020-02-28 13:26:17 +08001649 DVR_DEBUG(1, "get stat start [%p]", handle);
1650 //pthread_mutex_lock(&player->lock);
1651 //DVR_DEBUG(1, "lock func: %s", __func__);
1652 DVR_DEBUG(1, "get stat start id[%lld]", player->cur_segment_id);
hualing chen5cbe1a62020-02-10 16:36:36 +08001653
1654 p_status->state = player->state;
1655 p_status->segment_id = player->cur_segment_id;
1656 p_status->time_cur = _dvr_get_cur_time(handle);
hualing chencc91e1c2020-02-28 13:26:17 +08001657 p_status->time_end = _dvr_get_end_time(handle);
hualing chen5cbe1a62020-02-10 16:36:36 +08001658 memcpy(&p_status->pids, &player->cur_segment.pids, sizeof(DVR_PlaybackPids_t));
hualing chencc91e1c2020-02-28 13:26:17 +08001659 p_status->speed = player->cmd.speed.speed.speed;
hualing chen5cbe1a62020-02-10 16:36:36 +08001660 p_status->flags = player->cur_segment.flags;
hualing chencc91e1c2020-02-28 13:26:17 +08001661 //pthread_mutex_unlock(&player->lock);
1662 //DVR_DEBUG(1, "unlock func: %s", __func__);
1663 DVR_DEBUG(1, "get stat start end [%d][%d] id[%lld]", p_status->time_cur, p_status->time_end, p_status->segment_id);
hualing chenb31a6c62020-01-13 17:27:00 +08001664 return DVR_SUCCESS;
1665}
1666
hualing chen040df222020-01-17 13:35:02 +08001667void _dvr_dump_segment(DVR_PlaybackSegmentInfo_t *segment) {
1668 if (segment != NULL) {
hualing chen5cbe1a62020-02-10 16:36:36 +08001669 DVR_DEBUG(1, "segment id: %lld", segment->segment_id);
hualing chen040df222020-01-17 13:35:02 +08001670 DVR_DEBUG(1, "segment flag: %d", segment->flags);
1671 DVR_DEBUG(1, "segment location: [%s]", segment->location);
1672 DVR_DEBUG(1, "segment vpid: 0x%x vfmt:0x%x", segment->pids.video.pid,segment->pids.video.format);
1673 DVR_DEBUG(1, "segment apid: 0x%x afmt:0x%x", segment->pids.audio.pid,segment->pids.audio.format);
1674 DVR_DEBUG(1, "segment pcr pid: 0x%x pcr fmt:0x%x", segment->pids.pcr.pid,segment->pids.pcr.format);
1675 DVR_DEBUG(1, "segment sub apid: 0x%x sub afmt:0x%x", segment->pids.ad.pid,segment->pids.ad.format);
hualing chen86e7d482020-01-16 15:13:33 +08001676 }
hualing chenb31a6c62020-01-13 17:27:00 +08001677}
1678
hualing chen5cbe1a62020-02-10 16:36:36 +08001679int dvr_dump_segmentinfo(DVR_PlaybackHandle_t handle, uint64_t segment_id) {
hualing chen040df222020-01-17 13:35:02 +08001680 DVR_Playback_t *player = (DVR_Playback_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +08001681
hualing chen040df222020-01-17 13:35:02 +08001682 DVR_PlaybackSegmentInfo_t *segment;
1683 list_for_each_entry(segment, &player->segment_list, head)
hualing chen86e7d482020-01-16 15:13:33 +08001684 {
hualing chen040df222020-01-17 13:35:02 +08001685 if (segment_id >= 0) {
1686 if (segment->segment_id == segment_id) {
1687 _dvr_dump_segment(segment);
hualing chen86e7d482020-01-16 15:13:33 +08001688 break;
1689 }
1690 } else {
hualing chen5cbe1a62020-02-10 16:36:36 +08001691 //printf segment info
hualing chen040df222020-01-17 13:35:02 +08001692 _dvr_dump_segment(segment);
hualing chen86e7d482020-01-16 15:13:33 +08001693 }
1694 }
1695 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +08001696}