blob: 7056949f1f6df297d3022c0508c9560183447889 [file] [log] [blame]
hualing chenb31a6c62020-01-13 17:27:00 +08001#include <stdio.h>
2#include <stdlib.h>
3
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <sys/ioctl.h>
7#include <fcntl.h>
8#include <unistd.h>
9#include <poll.h>
10#include <errno.h>
11#include <signal.h>
12#include <pthread.h>
13
14
15#include "dvr_common.h"
16
17#include "dvr_playback.h"
18
19#define VALID_PID(_pid_) ((_pid_)>0 && (_pid_)<0x1fff)
20
hualing chen86e7d482020-01-16 15:13:33 +080021static int _dvr_playback_get_trick_stat(DVR_Playback_Handle_t handle)
22{
23 int state;
24 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
25
26 if (player->handle == -1)
27 return -1;
28
29 state = playback_device_get_trick_stat(handle);
30
31 return state;
32}
33
hualing chenb31a6c62020-01-13 17:27:00 +080034
35//timeout wait sibnal
hualing chen86e7d482020-01-16 15:13:33 +080036static int _dvr_playback_timeoutwait(DVR_Playback_Handle_t handle , int ms)
hualing chenb31a6c62020-01-13 17:27:00 +080037{
hualing chen86e7d482020-01-16 15:13:33 +080038 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +080039
hualing chen86e7d482020-01-16 15:13:33 +080040 struct timespec ts;
41 clock_gettime(CLOCK_MONOTONIC, &ts);
42 //ms为毫秒,换算成秒
43 ts.tv_sec += ms/1000;
44 //在outtime的基础上,增加ms毫秒
45 //outtime.tv_nsec为纳秒,1微秒=1000纳秒
46 //tv_nsec此值再加上剩余的毫秒数 ms%1000,有可能超过1秒。需要特殊处理
47 uint64_t us = ts.tv_nsec/1000 + 1000 * (ms % 1000); //微秒
48 //us的值有可能超过1秒,
49 ts.tv_sec += us / 1000000;
50 us = us % 1000000;
51 ts.tv_nsec = us * 1000;//换算成纳秒
hualing chenb31a6c62020-01-13 17:27:00 +080052
hualing chen86e7d482020-01-16 15:13:33 +080053 pthread_cond_timedwait(&player->cond, &player->lock, &ts);
54 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +080055}
56
57//send signal
hualing chen86e7d482020-01-16 15:13:33 +080058static int _dvr_playback_sendSignal(DVR_Playback_Handle_t handle)
hualing chenb31a6c62020-01-13 17:27:00 +080059{
hualing chen86e7d482020-01-16 15:13:33 +080060 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
61 pthread_cond_signal(&player->cond);
62 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +080063}
64
hualing chen86e7d482020-01-16 15:13:33 +080065static int _dvr_get_next_chunkid(DVR_Playback_Handle_t handle) {
hualing chenb31a6c62020-01-13 17:27:00 +080066
hualing chen86e7d482020-01-16 15:13:33 +080067 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
68 DVR_Playback_Chunk_Info_t *chunk;
69
70 int found = 0;
71
72 list_for_each_entry(chunk, &player->chunk_list, head)
73 {
74 if (player->cur_chunkid == -1) {
75 //get first chunk from list
76 found = 1;
77 } else if (chunk->chunk_id == player->cur_chunkid) {
78 //find cur chunk, we need get next one
79 found = 1;
80 continue;
81 }
82 if (found == 1) {
83 //get chunk info
84 player->cur_chunkid = chunk->chunk_id;
85 player->cur_chunk.chunk_id = chunk->chunk_id;
86 player->cur_chunk.flags = chunk->flags;
87 //cp location
88 memcpy(player->cur_chunk.location, chunk->location, DVR_MAX_LOCATION_SIZE);
89 //pids
90 memcpy(&player->cur_chunk.pids, &chunk->pids, sizeof(DVR_Playback_Pids_t));
91 found = 2;
92 }
93 }
94 if (found != 2) {
95 //list is null or reache list end
96 return -1;
97 }
98 return DVR_SUCCESS;
99}
100//open next chunk to play,if reach list end return errro.
101static int _change_to_next_chunk(DVR_Playback_Handle_t handle)
102{
103 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
104 Segment_OpenParams_t params;
105 int ret = DVR_SUCCESS;
106
107 int id = _dvr_get_next_chunkid(handle);
108 if (id < 0) {
109 DVR_DEBUG(1, "not found chunk info");
110 return -1;
111 }
112
113 if (player->r_handle != NULL) {
114 segment_close(player->r_handle);
115 player->r_handle = NULL;
116 }
117
118 memset(params.location, 0, DVR_MAX_LOCATION_SIZE);
119 //cp chur chunk path to location
120 strncpy(params.location, player->cur_chunk.location, strlen(player->cur_chunk.location));
121 params.segment_id = (uint64_t)player->cur_chunk.chunk_id;
122 params.mode = SEGMENT_MODE_READ;
123 ret = segment_open(&params, &(player->r_handle));
124 return ret;
125}
126
127static void* _dvr_playback_thread(void *arg)
128{
129 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) arg;
130 int need_open_chunk = 1;
131 Playback_Device_WBufs_t wbufs;
132
133 int timeout = 10;//ms
134 uint8_t *buf = NULL;
135 int buf_len = player->openParams.blocksize > 0 ? player->openParams.blocksize : (256 * 1024);
136 int real_read = 0;
137 int real_write = 0;
138
139
140 buf = malloc(buf_len);
141 wbufs.flag = 0;
142 wbufs.timeout = 10;
143 wbufs.len = 0;
144
145 int ret = _change_to_next_chunk((DVR_Playback_Handle_t)player);
146 if (ret != DVR_SUCCESS) {
147 if (buf != NULL) {
148 free(buf);
149 buf = NULL;
150 }
hualing chenb31a6c62020-01-13 17:27:00 +0800151 return NULL;
hualing chen86e7d482020-01-16 15:13:33 +0800152 }
153 int trick_stat = 0;
154 while (player->is_running/* || player->cmd.last_cmd != player->cmd.cur_cmd*/) {
hualing chenb31a6c62020-01-13 17:27:00 +0800155
hualing chen86e7d482020-01-16 15:13:33 +0800156 //check trick stat
157 pthread_mutex_lock(&player->lock);
158 trick_stat = _dvr_playback_get_trick_stat((DVR_Playback_Handle_t)player);
159 if (trick_stat > 0)
160 {
161 if (player->cmd.cur_cmd == DVR_PlayBack_Cmd_Seek) {
162 //check last cmd
163 if(player->cmd.last_cmd == DVR_PlayBack_Cmd_Pause
164 || (player->play_flag == DVR_PLAY_STARTED_PAUSEDLIVE
165 && (player->cmd.last_cmd == DVR_PlayBack_Cmd_VStart
166 || player->cmd.last_cmd == DVR_PlayBack_Cmd_AStart
167 || player->cmd.last_cmd == DVR_PlayBack_Cmd_Start))) {
hualing chenb31a6c62020-01-13 17:27:00 +0800168
hualing chen86e7d482020-01-16 15:13:33 +0800169 //need change to pause state
170 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Pause;
171 player->cmd.state = DVR_PlayBack_State_Pause;
172 playback_device_pause(player->handle);
173 }
174 } else if (player->cmd.cur_cmd == DVR_PlayBack_Cmd_FF
175 || player->cmd.cur_cmd == DVR_PlayBack_Cmd_FB) {
176
177 //restart play stream if speed > 2
178 }
hualing chenb31a6c62020-01-13 17:27:00 +0800179 }
hualing chen86e7d482020-01-16 15:13:33 +0800180 pthread_mutex_unlock(&player->lock);
181
182 int write = 0;
183 int read = segment_read(player->r_handle, buf + real_read, buf_len - real_read);
184 if (read == 0) {
185 //file end.need to play next chunk
186 int ret = _change_to_next_chunk((DVR_Playback_Handle_t)player);
187 if (ret != DVR_SUCCESS) {
188 if (player->openParams.is_timeshift) {
189 //continue,timeshift mode, when read end,need wait cur recording chunk
190 continue;
191 } else {
192 //play end
193 if (real_read == 0) {
194 DVR_DEBUG(1, "playback reach end chunk, exit playback");
195 break;
196 } else {
197 //has data not inject to dev
198 goto inject;
199 }
200 }
201 }
202 read = segment_read(player->r_handle, buf + real_read, buf_len - real_read);
203 }
204 real_read = real_read + read;
205 if (real_read < buf_len ) {
206 //continue to read
207 _dvr_playback_timeoutwait((DVR_Playback_Handle_t)player, timeout);
208 if (!player->is_running) {
209 break;
210 }
211 continue;
212 }
213inject:
214 wbufs.len = real_read;
215 real_write = 0;
216rewrite:
217 wbufs.buf = buf + real_write;
218 //read data
219 //descramble data
220 //read data to inject
221 write = playback_device_write(player->handle, &wbufs);
222 real_write = real_write + write;
223 wbufs.len = real_read - real_write;
224 //check if left data
225 if (real_write == real_read) {
226 //this block write end
227 } else {
228 _dvr_playback_timeoutwait((DVR_Playback_Handle_t)player, timeout);
229 if (!player->is_running) {
230 break;
231 }
232 goto rewrite;
233 }
234 }
235 return NULL;
hualing chenb31a6c62020-01-13 17:27:00 +0800236}
237
238
hualing chen86e7d482020-01-16 15:13:33 +0800239static int _start_playback_thread(DVR_Playback_Handle_t handle)
hualing chenb31a6c62020-01-13 17:27:00 +0800240{
hualing chen86e7d482020-01-16 15:13:33 +0800241 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
242 if (player->is_running) {
243 return 0;
244 }
245 int rc = pthread_create(&player->playback_thread, NULL, _dvr_playback_thread, (void*)player);
246 if (rc > 0)
247 player->is_running = 1;
248 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800249}
250
251
hualing chen86e7d482020-01-16 15:13:33 +0800252static int _stop_playback_thread(DVR_Playback_Handle_t handle)
253{
254 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
255 if (player->is_running)
256 {
257 player->is_running = DVR_FALSE;
258 pthread_cond_signal(&player->cond);
259 pthread_join(player->playback_thread, NULL);
260 }
261 if (player->r_handle) {
262 segment_close(player->r_handle);
263 player->r_handle = NULL;
264 }
265 return 0;
266}
267
hualing chenb31a6c62020-01-13 17:27:00 +0800268/**\brief Open an dvr palyback
269 * \param[out] p_handle dvr playback addr
270 * \param[in] params dvr playback open parameters
271 * \retval DVR_SUCCESS On success
272 * \return Error code
273 */
hualing chen86e7d482020-01-16 15:13:33 +0800274int dvr_playback_open(DVR_Playback_Handle_t *p_handle, DVR_PlayBack_OpenParams_t *params) {
hualing chenb31a6c62020-01-13 17:27:00 +0800275
hualing chen86e7d482020-01-16 15:13:33 +0800276 Dvr_PlayBack_t *player;
277 pthread_condattr_t cattr;
hualing chenb31a6c62020-01-13 17:27:00 +0800278
hualing chen86e7d482020-01-16 15:13:33 +0800279 player = (Dvr_PlayBack_t*)malloc(sizeof(Dvr_PlayBack_t));
hualing chenb31a6c62020-01-13 17:27:00 +0800280
hualing chen86e7d482020-01-16 15:13:33 +0800281 pthread_mutex_init(&player->lock, NULL);
282 pthread_condattr_init(&cattr);
283 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
284 pthread_cond_init(&player->cond, &cattr);
285 pthread_condattr_destroy(&cattr);
hualing chenb31a6c62020-01-13 17:27:00 +0800286
hualing chen86e7d482020-01-16 15:13:33 +0800287 //init chunk list head
288 INIT_LIST_HEAD(&player->chunk_list);
289 player->cmd.last_cmd = DVR_PlayBack_Cmd_Stop;
290 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Stop;
291 player->cmd.speed.speed = PlayBack_Speed_X1;
292 player->cmd.state = DVR_PlayBack_State_Stop;
293 player->cmd.pos = 0;
294 //store open params
295 player->openParams.dmx = params->dmx;
296 player->openParams.blocksize = params->blocksize;
297 player->openParams.is_timeshift = params->is_timeshift;
298 //init has audio and video
299 player->has_video = DVR_FALSE;
300 player->has_audio = DVR_FALSE;
hualing chenb31a6c62020-01-13 17:27:00 +0800301
hualing chen86e7d482020-01-16 15:13:33 +0800302 //device open
303 playback_device_open(&player->handle, params);
304 *p_handle = player;
305 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800306}
307
308/**\brief Close an dvr palyback
309 * \param[in] handle playback handle
310 * \retval DVR_SUCCESS On success
311 * \return Error code
312 */
313int dvr_playback_close(DVR_Playback_Handle_t handle) {
hualing chenb31a6c62020-01-13 17:27:00 +0800314
hualing chen86e7d482020-01-16 15:13:33 +0800315 DVR_ASSERT(handle);
hualing chenb31a6c62020-01-13 17:27:00 +0800316
hualing chen86e7d482020-01-16 15:13:33 +0800317 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
318
319 playback_device_close(player->handle);
320 //device close
321 pthread_mutex_destroy(&player->lock);
322 pthread_cond_destroy(&player->cond);
323 free(player);
324 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800325}
326
hualing chen86e7d482020-01-16 15:13:33 +0800327int dvr_playback_get_playinfo(int chunkid,
328Playback_Device_VideoParams_t *vparam,
329Playback_Device_AudioParams_t *aparam) {
hualing chenb31a6c62020-01-13 17:27:00 +0800330
331 return 0;
332}
333
334
335/**\brief Start play audio and video, used start auido api and start video api
336 * \param[in] handle playback handle
337 * \param[in] params audio playback params,contains fmt and pid...
338 * \retval DVR_SUCCESS On success
339 * \return Error code
340 */
hualing chen86e7d482020-01-16 15:13:33 +0800341int dvr_playback_start(DVR_Playback_Handle_t handle, DVR_Playback_Flag_t flag) {
342 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
343 Playback_Device_VideoParams_t vparams;
344 Playback_Device_AudioParams_t aparams;
345 int chunkid = -1;
hualing chenb31a6c62020-01-13 17:27:00 +0800346
hualing chen86e7d482020-01-16 15:13:33 +0800347 int sync = DVR_PLAY_SYNC;
348 player->play_flag = flag;
349 //get chunk info and audio video pid fmt ;
350 pthread_mutex_lock(&player->lock);
351 dvr_playback_get_playinfo(chunkid, &vparams, &aparams);
352 _start_playback_thread(handle);
353 //start audio and video
354 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
355 //audio abnd video pis is all invalid, return error.
356 DVR_DEBUG(0, "dvr play back start error, not found audio and video info");
357 return -1;
358 }
hualing chenb31a6c62020-01-13 17:27:00 +0800359
hualing chen86e7d482020-01-16 15:13:33 +0800360 if (sync == DVR_PLAY_SYNC) {
361 if (VALID_PID(vparams.pid)) {
362 player->has_video = DVR_TRUE;
363 playback_device_video_start(player->handle , &vparams);
364 //if set flag is pause live, we need set trick mode
365 if (player->play_flag & DVR_PLAY_STARTED_PAUSEDLIVE == DVR_PLAY_STARTED_PAUSEDLIVE) {
366 playback_device_trick_mode(player->handle, 1);
367 }
hualing chenb31a6c62020-01-13 17:27:00 +0800368 }
hualing chen86e7d482020-01-16 15:13:33 +0800369 if (VALID_PID(aparams.pid)) {
370 player->has_audio = DVR_TRUE;
371 playback_device_audio_start(player->handle , &aparams);
hualing chenb31a6c62020-01-13 17:27:00 +0800372 }
hualing chen86e7d482020-01-16 15:13:33 +0800373 player->cmd.last_cmd = player->cmd.cur_cmd;
374 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Start;
375 player->cmd.speed.speed = PlayBack_Speed_X1;
376 player->cmd.state = DVR_PlayBack_State_Start;
377 player->state = DVR_PlayBack_State_Start;
378 } else {
379
380 player->cmd.last_cmd = player->cmd.cur_cmd;
381 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Start;
382 player->cmd.speed.speed =PlayBack_Speed_X1;
383 player->cmd.state = DVR_PlayBack_State_Start;
384 pthread_cond_signal(&player->cond);
385 }
386 pthread_mutex_unlock(&player->lock);
387 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800388}
389/**\brief dvr play back add chunk info to chunk list
390 * \param[in] handle playback handle
391 * \param[in] info added chunk info,con vpid fmt apid fmt.....
392 * \retval DVR_SUCCESS On success
393 * \return Error code
394 */
hualing chen86e7d482020-01-16 15:13:33 +0800395int dvr_playback_add_chunk(DVR_Playback_Handle_t handle, DVR_Playback_Chunk_Info_t *info) {
396 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +0800397
hualing chen86e7d482020-01-16 15:13:33 +0800398 DVR_DEBUG(1, "add chunk id: %d", info->chunk_id);
399 DVR_Playback_Chunk_Info_t *chunk;
hualing chenb31a6c62020-01-13 17:27:00 +0800400
hualing chen86e7d482020-01-16 15:13:33 +0800401 chunk = malloc(sizeof(DVR_Playback_Chunk_Info_t));
402 memset(chunk, 0, sizeof(DVR_Playback_Chunk_Info_t));
hualing chenb31a6c62020-01-13 17:27:00 +0800403
hualing chen86e7d482020-01-16 15:13:33 +0800404 //not memcpy chun info.
405 chunk->chunk_id = info->chunk_id;
406 //cp location
407 memcpy(chunk->location, info->location, DVR_MAX_LOCATION_SIZE);
408 //pids
409 memcpy(&chunk->pids, &info->pids, sizeof(DVR_Playback_Pids_t));
410 chunk->flags = info->flags;
411 pthread_mutex_lock(&player->lock);
412 list_add_tail(&chunk->head, &player->chunk_list);
413 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +0800414
415 return DVR_SUCCESS;
416}
417/**\brief dvr play back remove chunk info by chunkid
418 * \param[in] handle playback handle
419 * \param[in] chunkid need removed chunk id
420 * \retval DVR_SUCCESS On success
421 * \return Error code
422 */
423int dvr_playback_remove_chunk(DVR_Playback_Handle_t handle, int chunk_id) {
hualing chen86e7d482020-01-16 15:13:33 +0800424 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
425 DVR_DEBUG(1, "remove chunk id: %d", chunk_id);
hualing chenb31a6c62020-01-13 17:27:00 +0800426
hualing chen86e7d482020-01-16 15:13:33 +0800427 pthread_mutex_lock(&player->lock);
428 DVR_Playback_Chunk_Info_t *chunk;
429 list_for_each_entry(chunk, &player->chunk_list, head)
430 {
431 if (chunk->chunk_id == chunk_id) {
432 list_del(&chunk->head);
433 free(chunk);
434 break;
hualing chenb31a6c62020-01-13 17:27:00 +0800435 }
hualing chen86e7d482020-01-16 15:13:33 +0800436 }
437 pthread_mutex_unlock(&player->lock);
438
439 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800440}
441/**\brief dvr play back add chunk info
442 * \param[in] handle playback handle
443 * \param[in] info added chunk info,con vpid fmt apid fmt.....
444 * \retval DVR_SUCCESS On success
445 * \return Error code
446 */
447int dvr_playback_Update_Chunk_Flags(DVR_Playback_Handle_t handle,
hualing chen86e7d482020-01-16 15:13:33 +0800448 int chunk_id, DVR_Playback_Chunk_Flag_t flags) {
449 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
450 DVR_DEBUG(1, "update chunk id: %d flag:%d", chunk_id, flags);
hualing chenb31a6c62020-01-13 17:27:00 +0800451
hualing chen86e7d482020-01-16 15:13:33 +0800452 DVR_Playback_Chunk_Info_t *chunk;
453 pthread_mutex_lock(&player->lock);
454 list_for_each_entry(chunk, &player->chunk_list, head)
455 {
456 if (chunk->chunk_id != chunk_id) {
457 continue;
hualing chenb31a6c62020-01-13 17:27:00 +0800458 }
hualing chen86e7d482020-01-16 15:13:33 +0800459 // if encramble to free, only set flag and return;
460
461 //if displayable to none, we need mute audio and video
462 if (chunk_id == player->cur_chunkid) {
463 if (chunk->flags & DVR_PLAY_DISPLAYABLE == DVR_PLAY_DISPLAYABLE &&
464 flags & DVR_PLAY_DISPLAYABLE == 0) {
465 //disable display
466 playback_device_mute_audio(player->handle, 1);
467 playback_device_mute_video(player->handle, 1);
468 } else if (chunk->flags & DVR_PLAY_DISPLAYABLE == 0 &&
469 flags & DVR_PLAY_DISPLAYABLE == DVR_PLAY_DISPLAYABLE) {
470 //enable display
471 playback_device_mute_audio(player->handle, 0);
472 playback_device_mute_video(player->handle, 0);
473 } else {
474 //do nothing
475 }
476 } else {
477 //do nothing
478 }
479 //continue , only set flag
480 chunk->flags = flags;
481 }
482 pthread_mutex_unlock(&player->lock);
483 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800484}
485
486
hualing chen86e7d482020-01-16 15:13:33 +0800487int _do_check_pid_info(DVR_Playback_Handle_t handle, DVR_Playback_StreamParams_t now_pid, DVR_Playback_StreamParams_t set_pid, int type) {
488 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +0800489
hualing chen86e7d482020-01-16 15:13:33 +0800490 if (now_pid.pid == set_pid.pid) {
491 //do nothing
hualing chenb31a6c62020-01-13 17:27:00 +0800492 return 0;
hualing chen86e7d482020-01-16 15:13:33 +0800493 } else {
494 if (VALID_PID(now_pid.pid)) {
495 //stop now stream
496 if (type == 0) {
497 //stop vieo
498 playback_device_video_stop(player->handle);
499 } else if (type == 1) {
500 //stop audio
501 playback_device_audio_stop(player->handle);
502 } else if (type == 2) {
503 //stop sub audio
504 playback_device_audio_stop(player->handle);
505 } else if (type == 3) {
506 //pcr
507 }
508 }
509 if (VALID_PID(set_pid.pid)) {
510 //start
511 if (type == 0) {
512 //start vieo
513 Playback_Device_VideoParams_t vparams;
514 vparams.pid = set_pid.pid;
515 vparams.fmt = set_pid.fmt;
516 dvr_playback_video_start(player->handle,&vparams);
517 } else if (type == 1) {
518 //start audio
519 Playback_Device_AudioParams_t aparams;
520 aparams.pid = set_pid.pid;
521 aparams.fmt = set_pid.fmt;
522 dvr_playback_audio_start(player->handle,&aparams);
523 } else if (type == 2) {
524 //start sub audio
525 Playback_Device_AudioParams_t aparams;
526 aparams.pid = set_pid.pid;
527 aparams.fmt = set_pid.fmt;
528 dvr_playback_audio_start(player->handle, &aparams);
529 } else if (type == 3) {
530 //pcr
531 }
532 }
533 }
534 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800535}
536/**\brief dvr play back update chunk pids
537 * if updated chunk is ongoing chunk, we need start new
538 * add pid stream and stop remove pid stream.
539 * \param[in] handle playback handle
540 * \param[in] chunk_id need updated pids chunk id
541 * \retval DVR_SUCCESS On success
542 * \return Error code
543 */
hualing chen86e7d482020-01-16 15:13:33 +0800544int dvr_playback_Update_Chunk_Pids(DVR_Playback_Handle_t handle, int chunk_id, DVR_Playback_Pids_t *p_pids) {
545 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
546 DVR_DEBUG(1, "update chunk id: %d", chunk_id);
hualing chenb31a6c62020-01-13 17:27:00 +0800547
hualing chen86e7d482020-01-16 15:13:33 +0800548 DVR_Playback_Chunk_Info_t *chunk;
549 pthread_mutex_lock(&player->lock);
550 list_for_each_entry(chunk, &player->chunk_list, head)
551 {
552 if (chunk->chunk_id == chunk_id) {
553 //check video pids, stop or restart
554 _do_check_pid_info(handle, chunk->pids.vpid, p_pids->vpid, 0);
555 //check audio pids stop or restart
556 _do_check_pid_info(handle, chunk->pids.apid, p_pids->apid, 1);
557 //check sub audio pids stop or restart
558 _do_check_pid_info(handle, chunk->pids.sub_apid, p_pids->sub_apid, 2);
559 //check pcr pids stop or restart
560 _do_check_pid_info(handle, chunk->pids.pcrpid, p_pids->pcrpid, 3);
561 //save pids info
562 memcpy(&chunk->pids, p_pids, sizeof(DVR_Playback_Pids_t));
563 break;
hualing chenb31a6c62020-01-13 17:27:00 +0800564 }
hualing chen86e7d482020-01-16 15:13:33 +0800565 }
566 pthread_mutex_unlock(&player->lock);
567 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800568}
569/**\brief Stop play, will stop video and audio
570 * \param[in] handle playback handle
571 * \param[in] clear is clear last frame
572 * \retval DVR_SUCCESS On success
573 * \return Error code
574 */
575int dvr_playback_stop(DVR_Playback_Handle_t handle, DVR_Bool_t clear) {
hualing chen86e7d482020-01-16 15:13:33 +0800576 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
577 pthread_mutex_lock(&player->lock);
578 playback_device_video_stop(player->handle);
579 playback_device_audio_stop(player->handle);
580 player->cmd.last_cmd = player->cmd.cur_cmd;
581 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Stop;
582 player->cmd.state = DVR_PlayBack_State_Stop;
583 player->state = DVR_PlayBack_State_Stop;
584 pthread_mutex_unlock(&player->lock);
585 //destory thread
586 _stop_playback_thread(handle);
587 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800588}
589/**\brief Start play audio
590 * \param[in] handle playback handle
591 * \param[in] params audio playback params,contains fmt and pid...
592 * \retval DVR_SUCCESS On success
593 * \return Error code
594 */
hualing chen86e7d482020-01-16 15:13:33 +0800595int dvr_playback_audio_start(DVR_Playback_Handle_t handle, Playback_Device_AudioParams_t *param) {
596 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
597 _start_playback_thread(handle);
598 //start audio and video
599 pthread_mutex_lock(&player->lock);
600 player->has_audio = DVR_TRUE;
601 playback_device_audio_start(player->handle , &param);
602 player->cmd.last_cmd = player->cmd.cur_cmd;
603 player->cmd.cur_cmd = DVR_PlayBack_Cmd_AStart;
604 player->cmd.state = DVR_PlayBack_State_Start;
605 player->state = DVR_PlayBack_State_Start;
606 pthread_mutex_unlock(&player->lock);
607 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800608}
609/**\brief Stop play audio
610 * \param[in] handle playback handle
611 * \retval DVR_SUCCESS On success
612 * \return Error code
613 */
614int dvr_playback_audio_stop(DVR_Playback_Handle_t handle) {
hualing chen86e7d482020-01-16 15:13:33 +0800615 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
616 pthread_mutex_lock(&player->lock);
617 player->has_audio = DVR_FALSE;
618 playback_device_audio_stop(player->handle);
619
620 player->cmd.last_cmd = player->cmd.cur_cmd;
621 player->cmd.cur_cmd = DVR_PlayBack_Cmd_AStop;
622
623 if (player->has_video == DVR_FALSE) {
624 player->cmd.state = DVR_PlayBack_State_Stop;
625 player->state = DVR_PlayBack_State_Stop;
626 //destory thread
627 _stop_playback_thread(handle);
628 } else {
629 //do nothing.video is playing
630 }
631 pthread_mutex_unlock(&player->lock);
632 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800633}
634/**\brief Start play video
635 * \param[in] handle playback handle
636 * \param[in] params video playback params,contains fmt and pid...
637 * \retval DVR_SUCCESS On success
638 * \return Error code
639 */
hualing chen86e7d482020-01-16 15:13:33 +0800640int dvr_playback_video_start(DVR_Playback_Handle_t handle, Playback_Device_VideoParams_t *param) {
641 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
642 _start_playback_thread(handle);
643 //start audio and video
644 pthread_mutex_lock(&player->lock);
645 player->has_video = DVR_TRUE;
646 playback_device_video_start(player->handle , param);
647 //if set flag is pause live, we need set trick mode
648 if (player->play_flag & DVR_PLAY_STARTED_PAUSEDLIVE == DVR_PLAY_STARTED_PAUSEDLIVE) {
649 playback_device_trick_mode(player->handle, 1);
650 }
651 player->cmd.last_cmd = player->cmd.cur_cmd;
652 player->cmd.cur_cmd = DVR_PlayBack_Cmd_VStart;
653 player->cmd.state = DVR_PlayBack_State_Start;
654 player->state = DVR_PlayBack_State_Start;
655 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +0800656 return DVR_SUCCESS;
657}
658/**\brief Stop play video
659 * \param[in] handle playback handle
660 * \retval DVR_SUCCESS On success
661 * \return Error code
662 */
663int dvr_playback_video_stop(DVR_Playback_Handle_t handle) {
664 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chen86e7d482020-01-16 15:13:33 +0800665 pthread_mutex_lock(&player->lock);
666 player->has_video = DVR_FALSE;
hualing chenb31a6c62020-01-13 17:27:00 +0800667 playback_device_video_stop(player->handle);
hualing chen86e7d482020-01-16 15:13:33 +0800668
669 player->cmd.last_cmd = player->cmd.cur_cmd;
670 player->cmd.cur_cmd = DVR_PlayBack_Cmd_VStop;
671
672 if (player->has_audio == DVR_FALSE) {
673 player->cmd.state = DVR_PlayBack_State_Stop;
674 player->state = DVR_PlayBack_State_Stop;
675 //destory thread
676 _stop_playback_thread(handle);
677 } else {
678 //do nothing.audio is playing
679 }
680 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +0800681 return DVR_SUCCESS;
682}
683/**\brief Pause play
684 * \param[in] handle playback handle
685 * \param[in] flush whether its internal buffers should be flushed
686 * \retval DVR_SUCCESS On success
687 * \return Error code
688 */
689int dvr_playback_pause(DVR_Playback_Handle_t handle, DVR_Bool_t flush) {
hualing chen86e7d482020-01-16 15:13:33 +0800690 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
691 pthread_mutex_lock(&player->lock);
692 playback_device_pause(player->handle);
693 player->cmd.last_cmd = player->cmd.cur_cmd;
694 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Pause;
695 player->cmd.state = DVR_PlayBack_State_Pause;
696 player->state = DVR_PlayBack_State_Pause;
697 pthread_mutex_unlock(&player->lock);
698 return DVR_SUCCESS;
hualing chenb31a6c62020-01-13 17:27:00 +0800699}
700
701/**\brief seek
702 * \param[in] handle playback handle
703 * \param[in] time_offset time offset base cur chunk
704 * \retval DVR_SUCCESS On success
705 * \return Error code
706 */
707int dvr_playback_seek(DVR_Playback_Handle_t handle, int chunk_id, int time_offset) {
hualing chen86e7d482020-01-16 15:13:33 +0800708 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +0800709
hualing chen86e7d482020-01-16 15:13:33 +0800710 pthread_mutex_lock(&player->lock);
711 int offset = -1;
712 //get file offset by time
713 offset = segment_seek(player->r_handle, time_offset);
714 DVR_DEBUG(0, "seek get offset by time offset");
715 //seek file
716 DVR_DEBUG(0, "seek file offset");
717 if (offset == -1) {
718 //seek 2M data once for test
719 //seek error
720 offset = player->offset + (2*1014*1024);
721 }
722 player->offset = offset;
723
724 //stop play
725 DVR_DEBUG(0, "seek stop play, not inject data");
726 if (player->has_video)
hualing chenb31a6c62020-01-13 17:27:00 +0800727 playback_device_video_stop(player->handle);
hualing chen86e7d482020-01-16 15:13:33 +0800728 if (player->has_video)
hualing chenb31a6c62020-01-13 17:27:00 +0800729 playback_device_audio_stop(player->handle);
hualing chen86e7d482020-01-16 15:13:33 +0800730 //start play
731 Playback_Device_VideoParams_t vparams;
732 Playback_Device_AudioParams_t aparams;
733 int chunkid = player->cur_chunkid;
hualing chenb31a6c62020-01-13 17:27:00 +0800734
hualing chen86e7d482020-01-16 15:13:33 +0800735 int sync = DVR_PLAY_SYNC;
736 //get chunk info and audio video pid fmt ;
737 dvr_playback_get_playinfo(chunkid, &vparams, &aparams);
738 //start audio and video
739 if (!VALID_PID(vparams.pid) && !VALID_PID(aparams.pid)) {
740 //audio abnd video pis is all invalid, return error.
741 DVR_DEBUG(0, "seek start dvr play back start error, not found audio and video info");
742 pthread_mutex_unlock(&player->lock);
743 return -1;
744 }
745 //add
746 if (sync == DVR_PLAY_SYNC) {
747 if (VALID_PID(vparams.pid)) {
748 player->has_video;
749 playback_device_video_start(player->handle , &vparams);
hualing chenb31a6c62020-01-13 17:27:00 +0800750 }
hualing chen86e7d482020-01-16 15:13:33 +0800751 if (VALID_PID(aparams.pid)) {
752 player->has_video;
753 playback_device_audio_start(player->handle , &aparams);
hualing chenb31a6c62020-01-13 17:27:00 +0800754 }
hualing chen86e7d482020-01-16 15:13:33 +0800755 }
756 player->cmd.last_cmd = player->cmd.cur_cmd;
757 player->cmd.cur_cmd = DVR_PlayBack_Cmd_Seek;
758 player->cmd.state = DVR_PlayBack_State_Start;
759 player->state = DVR_PlayBack_State_Start;
760 pthread_mutex_unlock(&player->lock);
hualing chenb31a6c62020-01-13 17:27:00 +0800761
762 return DVR_SUCCESS;
763}
764/**\brief Set play speed
765 * \param[in] handle playback handle
766 * \param[in] speed playback speed
767 * \retval DVR_SUCCESS On success
768 * \return Error code
769 */
hualing chen86e7d482020-01-16 15:13:33 +0800770int dvr_playback_set_speed(DVR_Playback_Handle_t handle, Playback_Device_Speeds_t speed) {
hualing chenb31a6c62020-01-13 17:27:00 +0800771
772 return DVR_SUCCESS;
773}
774/**\brief Get playback status
775 * \param[in] handle playback handle
776 * \param[out] p_status playback status
777 * \retval DVR_SUCCESS On success
778 * \return Error code
779 */
780int dvr_playback_get_status(DVR_Playback_Handle_t handle,
hualing chen86e7d482020-01-16 15:13:33 +0800781  DVR_Playback_Status_t *p_status) {
hualing chenb31a6c62020-01-13 17:27:00 +0800782 return DVR_SUCCESS;
783}
784
hualing chen86e7d482020-01-16 15:13:33 +0800785void _dvr_dump_chunk(DVR_Playback_Chunk_Info_t *chunk) {
786 if (chunk != NULL) {
787 DVR_DEBUG(1, "chunk id: %d", chunk->chunk_id);
788 DVR_DEBUG(1, "chunk flag: %d", chunk->flags);
789 DVR_DEBUG(1, "chunk location: [%s]", chunk->location);
790 DVR_DEBUG(1, "chunk vpid: 0x%x vfmt:0x%x", chunk->pids.vpid.pid,chunk->pids.vpid.fmt);
791 DVR_DEBUG(1, "chunk apid: 0x%x afmt:0x%x", chunk->pids.apid.pid,chunk->pids.apid.fmt);
792 DVR_DEBUG(1, "chunk pcr pid: 0x%x pcr fmt:0x%x", chunk->pids.pcrpid.pid,chunk->pids.pcrpid.fmt);
793 DVR_DEBUG(1, "chunk sub apid: 0x%x sub afmt:0x%x", chunk->pids.sub_apid.pid,chunk->pids.sub_apid.fmt);
794 }
hualing chenb31a6c62020-01-13 17:27:00 +0800795}
796
797int dvr_dump_chunkinfo(DVR_Playback_Handle_t handle, int chunk_id) {
hualing chen86e7d482020-01-16 15:13:33 +0800798 Dvr_PlayBack_t *player = (Dvr_PlayBack_t *) handle;
hualing chenb31a6c62020-01-13 17:27:00 +0800799
hualing chen86e7d482020-01-16 15:13:33 +0800800 DVR_Playback_Chunk_Info_t *chunk;
801 list_for_each_entry(chunk, &player->chunk_list, head)
802 {
803 if (chunk_id >= 0) {
804 if (chunk->chunk_id == chunk_id) {
805 _dvr_dump_chunk(chunk);
806 break;
807 }
808 } else {
809 //printf chunk info
810 _dvr_dump_chunk(chunk);
811 }
812 }
813 return 0;
hualing chenb31a6c62020-01-13 17:27:00 +0800814}