chuangcheng.peng | 60c4828 | 2024-04-12 10:16:35 +0800 | [diff] [blame^] | 1 | #ifdef _FORTIFY_SOURCE |
| 2 | #undef _FORTIFY_SOURCE |
| 3 | #endif |
| 4 | /*************************************************************************** |
| 5 | * Copyright (c) 2014 Amlogic, Inc. All rights reserved. |
| 6 | * |
| 7 | * This source code is subject to the terms and conditions defined in the |
| 8 | * file 'LICENSE' which is part of this source code package. |
| 9 | * |
| 10 | * Description: |
| 11 | */ |
| 12 | /**\file |
| 13 | * \brief |
| 14 | * |
| 15 | * \author Gong Ke <ke.gong@amlogic.com> |
| 16 | * \date 2010-05-21: create the document |
| 17 | ***************************************************************************/ |
| 18 | |
| 19 | #define AM_DEBUG_LEVEL 1 |
| 20 | |
| 21 | //#include <am_debug.h> |
| 22 | #include "am_mem.h" |
| 23 | #include "am_dmx_internal.h" |
| 24 | #include "am_adp_internal.h" |
| 25 | #include <string.h> |
| 26 | #include <assert.h> |
| 27 | #include <unistd.h> |
| 28 | #include <stdio.h> |
| 29 | #include <stdlib.h> |
| 30 | //#include "am_misc.h" |
| 31 | |
| 32 | /**************************************************************************** |
| 33 | * Macro definitions |
| 34 | ***************************************************************************/ |
| 35 | |
| 36 | //#define DMX_WAIT_CB /*Wait callback function stop in API*/ |
| 37 | |
| 38 | #define DMX_SYNC |
| 39 | |
| 40 | #define DMX_BUF_SIZE (4096) |
| 41 | #define DMX_POLL_TIMEOUT (200) |
| 42 | #define DMX_DEV_COUNT (32) |
| 43 | |
| 44 | #define DMX_CHAN_ISSET_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]&(1<<((fid)&3))) |
| 45 | #define DMX_CHAN_SET_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]|=(1<<((fid)&3))) |
| 46 | #define DMX_CHAN_CLR_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]&=~(1<<((fid)&3))) |
| 47 | |
| 48 | /**************************************************************************** |
| 49 | * Static data |
| 50 | ***************************************************************************/ |
| 51 | |
| 52 | #ifdef EMU_DEMUX |
| 53 | extern const AM_DMX_Driver_t emu_dmx_drv; |
| 54 | #define HW_DMX_DRV emu_dmx_drv |
| 55 | #else |
| 56 | extern const AM_DMX_Driver_t linux_dvb_dmx_drv; |
| 57 | #define HW_DMX_DRV linux_dvb_dmx_drv |
| 58 | #endif |
| 59 | //extern const AM_DMX_Driver_t dvr_dmx_drv; |
| 60 | //#define SW_DMX_DRV dvr_dmx_drv |
| 61 | |
| 62 | static AM_DMX_Device_t dmx_devices[DMX_DEV_COUNT] = |
| 63 | { |
| 64 | #ifdef EMU_DEMUX |
| 65 | { |
| 66 | .drv = &emu_dmx_drv, |
| 67 | .src = AM_DMX_SRC_TS0 |
| 68 | }, |
| 69 | { |
| 70 | .drv = &emu_dmx_drv, |
| 71 | .src = AM_DMX_SRC_TS0 |
| 72 | } |
| 73 | #else |
| 74 | { |
| 75 | .drv = &linux_dvb_dmx_drv, |
| 76 | .src = AM_DMX_SRC_TS0 |
| 77 | }, |
| 78 | { |
| 79 | .drv = &linux_dvb_dmx_drv, |
| 80 | .src = AM_DMX_SRC_TS0 |
| 81 | }, |
| 82 | { |
| 83 | .drv = &linux_dvb_dmx_drv, |
| 84 | .src = AM_DMX_SRC_TS0 |
| 85 | }, |
| 86 | { |
| 87 | .drv = &linux_dvb_dmx_drv, |
| 88 | .src = AM_DMX_SRC_TS0 |
| 89 | } |
| 90 | #endif |
| 91 | }; |
| 92 | static void init_dmx_dev() { |
| 93 | static int init_dmx_dev_flag = 0; |
| 94 | int i = 0; |
| 95 | |
| 96 | if (!init_dmx_dev_flag) { |
| 97 | init_dmx_dev_flag = 1; |
| 98 | |
| 99 | for (i = 0; i < DMX_DEV_COUNT; i++) { |
| 100 | dmx_devices[i].drv = &linux_dvb_dmx_drv; |
| 101 | dmx_devices[i].src = AM_DMX_SRC_TS0; |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | /**************************************************************************** |
| 106 | * Static functions |
| 107 | ***************************************************************************/ |
| 108 | |
| 109 | /**\brief 根据设备号取得设备结构指针*/ |
| 110 | static AM_INLINE AM_ErrorCode_t dmx_get_dev(int dev_no, AM_DMX_Device_t **dev) |
| 111 | { |
| 112 | if (dev_no < 0 || dev_no >= DMX_DEV_COUNT) { |
| 113 | printf("invalid demux device number %d, must in(%d~%d)", dev_no, 0, DMX_DEV_COUNT-1); |
| 114 | return AM_DMX_ERR_INVALID_DEV_NO; |
| 115 | } |
| 116 | |
| 117 | *dev = &dmx_devices[dev_no]; |
| 118 | return AM_SUCCESS; |
| 119 | } |
| 120 | |
| 121 | /**\brief 根据设备号取得设备结构并检查设备是否已经打开*/ |
| 122 | static AM_INLINE AM_ErrorCode_t dmx_get_opened_dev(int dev_no, AM_DMX_Device_t **dev) |
| 123 | { |
| 124 | AM_TRY(dmx_get_dev(dev_no, dev)); |
| 125 | |
| 126 | if ((*dev)->open_count <= 0) { |
| 127 | printf("demux device %d has not been opened", dev_no); |
| 128 | return AM_DMX_ERR_INVALID_DEV_NO; |
| 129 | } |
| 130 | |
| 131 | return AM_SUCCESS; |
| 132 | } |
| 133 | |
| 134 | /**\brief 根据ID取得对应filter结构,并检查设备是否在使用*/ |
| 135 | static AM_INLINE AM_ErrorCode_t dmx_get_used_filter(AM_DMX_Device_t *dev, int filter_id, AM_DMX_Filter_t **pf) |
| 136 | { |
| 137 | AM_DMX_Filter_t *filter; |
| 138 | |
| 139 | if (filter_id < 0 || filter_id >= DMX_FILTER_COUNT) { |
| 140 | printf("invalid filter id, must in %d~%d", 0, DMX_FILTER_COUNT-1); |
| 141 | return AM_DMX_ERR_INVALID_ID; |
| 142 | } |
| 143 | |
| 144 | filter = &dev->filters[filter_id]; |
| 145 | |
| 146 | if (!filter->used) |
| 147 | { |
| 148 | printf("filter %d has not been allocated", filter_id); |
| 149 | return AM_DMX_ERR_NOT_ALLOCATED; |
| 150 | } |
| 151 | |
| 152 | *pf = filter; |
| 153 | return AM_SUCCESS; |
| 154 | } |
| 155 | |
| 156 | /**\brief 数据检测线程*/ |
| 157 | static void* dmx_data_thread(void *arg) |
| 158 | { |
| 159 | AM_DMX_Device_t *dev = (AM_DMX_Device_t*)arg; |
| 160 | uint8_t *sec_buf; |
| 161 | uint8_t *sec; |
| 162 | int sec_len; |
| 163 | AM_DMX_FilterMask_t mask; |
| 164 | AM_ErrorCode_t ret; |
| 165 | |
| 166 | #define BUF_SIZE (4096) |
| 167 | |
| 168 | sec_buf = (uint8_t*)malloc(BUF_SIZE); |
| 169 | |
| 170 | while (dev->enable_thread) { |
| 171 | AM_DMX_FILTER_MASK_CLEAR(&mask); |
| 172 | int id; |
| 173 | |
| 174 | ret = dev->drv->poll(dev, &mask, DMX_POLL_TIMEOUT); |
| 175 | if (ret == AM_SUCCESS) { |
| 176 | if (AM_DMX_FILTER_MASK_ISEMPTY(&mask)) |
| 177 | continue; |
| 178 | |
| 179 | #if defined(DMX_WAIT_CB) || defined(DMX_SYNC) |
| 180 | pthread_mutex_lock(&dev->lock); |
| 181 | dev->flags |= DMX_FL_RUN_CB; |
| 182 | pthread_mutex_unlock(&dev->lock); |
| 183 | #endif |
| 184 | |
| 185 | for (id = 0; id < DMX_FILTER_COUNT; id++) { |
| 186 | AM_DMX_Filter_t *filter = &dev->filters[id]; |
| 187 | AM_DMX_DataCb cb; |
| 188 | void *data; |
| 189 | |
| 190 | if (!AM_DMX_FILTER_MASK_ISSET(&mask, id)) |
| 191 | continue; |
| 192 | |
| 193 | if (!filter->enable || !filter->used) |
| 194 | continue; |
| 195 | |
| 196 | sec_len = BUF_SIZE; |
| 197 | |
| 198 | #ifndef DMX_WAIT_CB |
| 199 | pthread_mutex_lock(&dev->lock); |
| 200 | #endif |
| 201 | if (!filter->enable || !filter->used) { |
| 202 | ret = AM_FAILURE; |
| 203 | } else { |
| 204 | cb = filter->cb; |
| 205 | data = filter->user_data; |
| 206 | ret = dev->drv->read(dev, filter, sec_buf, &sec_len); |
| 207 | } |
| 208 | #ifndef DMX_WAIT_CB |
| 209 | pthread_mutex_unlock(&dev->lock); |
| 210 | #endif |
| 211 | if (ret == AM_DMX_ERR_TIMEOUT) { |
| 212 | sec = NULL; |
| 213 | sec_len = 0; |
| 214 | } else if (ret != AM_SUCCESS) { |
| 215 | continue; |
| 216 | } else { |
| 217 | sec = sec_buf; |
| 218 | } |
| 219 | |
| 220 | if (cb) { |
| 221 | if (id && sec) |
| 222 | printf("filter %d data callback len fd:%ld len:%d, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", |
| 223 | id, (long)filter->drv_data, sec_len, |
| 224 | sec[0], sec[1], sec[2], sec[3], sec[4], |
| 225 | sec[5], sec[6], sec[7], sec[8], sec[9]); |
| 226 | cb(dev->dev_no, id, sec, sec_len, data); |
| 227 | if (id && sec) |
| 228 | printf("filter %d data callback ok", id); |
| 229 | } |
| 230 | } |
| 231 | #if defined(DMX_WAIT_CB) || defined(DMX_SYNC) |
| 232 | pthread_mutex_lock(&dev->lock); |
| 233 | dev->flags &= ~DMX_FL_RUN_CB; |
| 234 | pthread_mutex_unlock(&dev->lock); |
| 235 | pthread_cond_broadcast(&dev->cond); |
| 236 | #endif |
| 237 | } else { |
| 238 | usleep(10000); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | if (sec_buf) { |
| 243 | free(sec_buf); |
| 244 | } |
| 245 | |
| 246 | return NULL; |
| 247 | } |
| 248 | |
| 249 | /**\brief 等待回调函数停止运行*/ |
| 250 | static AM_INLINE AM_ErrorCode_t dmx_wait_cb(AM_DMX_Device_t *dev) |
| 251 | { |
| 252 | #ifdef DMX_WAIT_CB |
| 253 | if (dev->thread != pthread_self()) { |
| 254 | while (dev->flags & DMX_FL_RUN_CB) |
| 255 | pthread_cond_wait(&dev->cond, &dev->lock); |
| 256 | } |
| 257 | #else |
| 258 | UNUSED(dev); |
| 259 | #endif |
| 260 | return AM_SUCCESS; |
| 261 | } |
| 262 | |
| 263 | /**\brief 停止Section过滤器*/ |
| 264 | static AM_ErrorCode_t dmx_stop_filter(AM_DMX_Device_t *dev, AM_DMX_Filter_t *filter) |
| 265 | { |
| 266 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 267 | |
| 268 | if (!filter->used || !filter->enable) { |
| 269 | return ret; |
| 270 | } |
| 271 | |
| 272 | if (dev->drv->enable_filter) { |
| 273 | ret = dev->drv->enable_filter(dev, filter, AM_FALSE); |
| 274 | } |
| 275 | |
| 276 | if (ret >= 0) { |
| 277 | filter->enable = AM_FALSE; |
| 278 | } |
| 279 | |
| 280 | return ret; |
| 281 | } |
| 282 | |
| 283 | /**\brief 释放过滤器*/ |
| 284 | static int dmx_free_filter(AM_DMX_Device_t *dev, AM_DMX_Filter_t *filter) |
| 285 | { |
| 286 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 287 | |
| 288 | if (!filter->used) |
| 289 | return ret; |
| 290 | |
| 291 | ret = dmx_stop_filter(dev, filter); |
| 292 | |
| 293 | if (ret == AM_SUCCESS) { |
| 294 | if (dev->drv->free_filter) { |
| 295 | ret = dev->drv->free_filter(dev, filter); |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | if (ret == AM_SUCCESS) { |
| 300 | filter->used = AM_FALSE; |
| 301 | } |
| 302 | |
| 303 | return ret; |
| 304 | } |
| 305 | |
| 306 | /**************************************************************************** |
| 307 | * API functions |
| 308 | ***************************************************************************/ |
| 309 | |
| 310 | /**\brief 打开解复用设备 |
| 311 | * \param dev_no 解复用设备号 |
| 312 | * \param[in] para 解复用设备开启参数 |
| 313 | * \return |
| 314 | * - AM_SUCCESS 成功 |
| 315 | * - 其他值 错误代码(见am_dmx.h) |
| 316 | */ |
| 317 | AM_ErrorCode_t AM_DMX_Open(int dev_no, const AM_DMX_OpenPara_t *para) |
| 318 | { |
| 319 | AM_DMX_Device_t *dev; |
| 320 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 321 | |
| 322 | assert(para); |
| 323 | |
| 324 | init_dmx_dev(); |
| 325 | |
| 326 | AM_TRY(dmx_get_dev(dev_no, &dev)); |
| 327 | |
| 328 | // pthread_mutex_lock(&am_gAdpLock); |
| 329 | |
| 330 | if (dev->open_count > 0) { |
| 331 | printf("demux device %d has already been opened", dev_no); |
| 332 | dev->open_count++; |
| 333 | ret = AM_SUCCESS; |
| 334 | goto final; |
| 335 | } |
| 336 | |
| 337 | dev->dev_no = dev_no; |
| 338 | |
| 339 | if (para->use_sw_filter) { |
| 340 | // dev->drv = &SW_DMX_DRV; |
| 341 | } else { |
| 342 | dev->drv = &HW_DMX_DRV; |
| 343 | } |
| 344 | |
| 345 | if (dev->drv->open) { |
| 346 | ret = dev->drv->open(dev, para); |
| 347 | } |
| 348 | |
| 349 | if (ret == AM_SUCCESS) { |
| 350 | pthread_mutex_init(&dev->lock, NULL); |
| 351 | pthread_cond_init(&dev->cond, NULL); |
| 352 | dev->enable_thread = AM_TRUE; |
| 353 | dev->flags = 0; |
| 354 | |
| 355 | if (pthread_create(&dev->thread, NULL, dmx_data_thread, dev)) { |
| 356 | pthread_mutex_destroy(&dev->lock); |
| 357 | pthread_cond_destroy(&dev->cond); |
| 358 | ret = AM_DMX_ERR_CANNOT_CREATE_THREAD; |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | if (ret == AM_SUCCESS) { |
| 363 | dev->open_count = 1; |
| 364 | } |
| 365 | final: |
| 366 | // pthread_mutex_unlock(&am_gAdpLock); |
| 367 | |
| 368 | return ret; |
| 369 | } |
| 370 | |
| 371 | /**\brief 关闭解复用设备 |
| 372 | * \param dev_no 解复用设备号 |
| 373 | * \return |
| 374 | * - AM_SUCCESS 成功 |
| 375 | * - 其他值 错误代码(见am_dmx.h) |
| 376 | */ |
| 377 | AM_ErrorCode_t AM_DMX_Close(int dev_no) |
| 378 | { |
| 379 | AM_DMX_Device_t *dev; |
| 380 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 381 | int i; |
| 382 | |
| 383 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 384 | |
| 385 | // pthread_mutex_lock(&am_gAdpLock); |
| 386 | |
| 387 | if (dev->open_count == 1) { |
| 388 | dev->enable_thread = AM_FALSE; |
| 389 | pthread_join(dev->thread, NULL); |
| 390 | |
| 391 | for (i = 0; i < DMX_FILTER_COUNT; i++) { |
| 392 | dmx_free_filter(dev, &dev->filters[i]); |
| 393 | } |
| 394 | |
| 395 | if (dev->drv->close) { |
| 396 | dev->drv->close(dev); |
| 397 | } |
| 398 | |
| 399 | pthread_mutex_destroy(&dev->lock); |
| 400 | pthread_cond_destroy(&dev->cond); |
| 401 | } |
| 402 | dev->open_count--; |
| 403 | |
| 404 | // pthread_mutex_unlock(&am_gAdpLock); |
| 405 | |
| 406 | return ret; |
| 407 | } |
| 408 | |
| 409 | /**\brief 分配一个过滤器 |
| 410 | * \param dev_no 解复用设备号 |
| 411 | * \param[out] fhandle 返回过滤器句柄 |
| 412 | * \return |
| 413 | * - AM_SUCCESS 成功 |
| 414 | * - 其他值 错误代码(见am_dmx.h) |
| 415 | */ |
| 416 | AM_ErrorCode_t AM_DMX_AllocateFilter(int dev_no, int *fhandle) |
| 417 | { |
| 418 | AM_DMX_Device_t *dev; |
| 419 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 420 | int fid; |
| 421 | |
| 422 | assert(fhandle); |
| 423 | |
| 424 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 425 | |
| 426 | pthread_mutex_lock(&dev->lock); |
| 427 | |
| 428 | for (fid = 0; fid < DMX_FILTER_COUNT; fid++) { |
| 429 | if (!dev->filters[fid].used) |
| 430 | break; |
| 431 | } |
| 432 | |
| 433 | if (fid >= DMX_FILTER_COUNT) { |
| 434 | printf("no free section filter"); |
| 435 | ret = AM_DMX_ERR_NO_FREE_FILTER; |
| 436 | } |
| 437 | |
| 438 | if (ret == AM_SUCCESS) { |
| 439 | dmx_wait_cb(dev); |
| 440 | |
| 441 | dev->filters[fid].id = fid; |
| 442 | if (dev->drv->alloc_filter) { |
| 443 | ret = dev->drv->alloc_filter(dev, &dev->filters[fid]); |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | if (ret == AM_SUCCESS) { |
| 448 | dev->filters[fid].used = AM_TRUE; |
| 449 | *fhandle = fid; |
| 450 | } |
| 451 | |
| 452 | pthread_mutex_unlock(&dev->lock); |
| 453 | |
| 454 | return ret; |
| 455 | } |
| 456 | |
| 457 | /**\brief 设定Section过滤器 |
| 458 | * \param dev_no 解复用设备号 |
| 459 | * \param fhandle 过滤器句柄 |
| 460 | * \param[in] params Section过滤器参数 |
| 461 | * \return |
| 462 | * - AM_SUCCESS 成功 |
| 463 | * - 其他值 错误代码(见am_dmx.h) |
| 464 | */ |
| 465 | AM_ErrorCode_t AM_DMX_SetSecFilter(int dev_no, int fhandle, const struct dmx_sct_filter_params *params) |
| 466 | { |
| 467 | AM_DMX_Device_t *dev; |
| 468 | AM_DMX_Filter_t *filter; |
| 469 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 470 | |
| 471 | assert(params); |
| 472 | |
| 473 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 474 | |
| 475 | if (!dev->drv->set_sec_filter) { |
| 476 | printf("demux do not support set_sec_filter"); |
| 477 | return AM_DMX_ERR_NOT_SUPPORTED; |
| 478 | } |
| 479 | |
| 480 | pthread_mutex_lock(&dev->lock); |
| 481 | |
| 482 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 483 | |
| 484 | if (ret == AM_SUCCESS) { |
| 485 | dmx_wait_cb(dev); |
| 486 | ret = dmx_stop_filter(dev, filter); |
| 487 | } |
| 488 | |
| 489 | if (ret == AM_SUCCESS) { |
| 490 | ret = dev->drv->set_sec_filter(dev, filter, params); |
| 491 | printf("set sec filter %d PID: %d filter: %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x", |
| 492 | fhandle, params->pid, |
| 493 | params->filter.filter[0], params->filter.mask[0], |
| 494 | params->filter.filter[1], params->filter.mask[1], |
| 495 | params->filter.filter[2], params->filter.mask[2], |
| 496 | params->filter.filter[3], params->filter.mask[3], |
| 497 | params->filter.filter[4], params->filter.mask[4], |
| 498 | params->filter.filter[5], params->filter.mask[5], |
| 499 | params->filter.filter[6], params->filter.mask[6], |
| 500 | params->filter.filter[7], params->filter.mask[7]); |
| 501 | } |
| 502 | |
| 503 | pthread_mutex_unlock(&dev->lock); |
| 504 | |
| 505 | return ret; |
| 506 | } |
| 507 | |
| 508 | /**\brief 设定PES过滤器 |
| 509 | * \param dev_no 解复用设备号 |
| 510 | * \param fhandle 过滤器句柄 |
| 511 | * \param[in] params PES过滤器参数 |
| 512 | * \return |
| 513 | * - AM_SUCCESS 成功 |
| 514 | * - 其他值 错误代码(见am_dmx.h) |
| 515 | */ |
| 516 | AM_ErrorCode_t AM_DMX_SetPesFilter(int dev_no, int fhandle, const struct dmx_pes_filter_params *params) |
| 517 | { |
| 518 | AM_DMX_Device_t *dev; |
| 519 | AM_DMX_Filter_t *filter; |
| 520 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 521 | |
| 522 | assert(params); |
| 523 | |
| 524 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 525 | |
| 526 | if (!dev->drv->set_pes_filter) { |
| 527 | printf("demux do not support set_pes_filter"); |
| 528 | return AM_DMX_ERR_NOT_SUPPORTED; |
| 529 | } |
| 530 | |
| 531 | pthread_mutex_lock(&dev->lock); |
| 532 | |
| 533 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 534 | |
| 535 | if (ret == AM_SUCCESS) { |
| 536 | dmx_wait_cb(dev); |
| 537 | ret = dmx_stop_filter(dev, filter); |
| 538 | } |
| 539 | |
| 540 | if (ret == AM_SUCCESS) { |
| 541 | ret = dev->drv->set_pes_filter(dev, filter, params); |
| 542 | printf("set pes filter %d PID %d", fhandle, params->pid); |
| 543 | } |
| 544 | |
| 545 | pthread_mutex_unlock(&dev->lock); |
| 546 | |
| 547 | return ret; |
| 548 | } |
| 549 | AM_ErrorCode_t AM_DMX_GetSTC(int dev_no, int fhandle) |
| 550 | { |
| 551 | AM_DMX_Device_t *dev; |
| 552 | AM_DMX_Filter_t *filter; |
| 553 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 554 | |
| 555 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 556 | printf("%s line:%d\n", __FUNCTION__, __LINE__); |
| 557 | if (!dev->drv->get_stc) { |
| 558 | printf("demux do not support set_pes_filter"); |
| 559 | return AM_DMX_ERR_NOT_SUPPORTED; |
| 560 | } |
| 561 | |
| 562 | pthread_mutex_lock(&dev->lock); |
| 563 | |
| 564 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 565 | |
| 566 | if (ret == AM_SUCCESS) { |
| 567 | ret = dev->drv->get_stc(dev, filter); |
| 568 | } |
| 569 | |
| 570 | pthread_mutex_unlock(&dev->lock); |
| 571 | printf("%s line:%d\n", __FUNCTION__, __LINE__); |
| 572 | |
| 573 | return ret; |
| 574 | } |
| 575 | |
| 576 | |
| 577 | /**\brief 释放一个过滤器 |
| 578 | * \param dev_no 解复用设备号 |
| 579 | * \param fhandle 过滤器句柄 |
| 580 | * \return |
| 581 | * - AM_SUCCESS 成功 |
| 582 | * - 其他值 错误代码(见am_dmx.h) |
| 583 | */ |
| 584 | AM_ErrorCode_t AM_DMX_FreeFilter(int dev_no, int fhandle) |
| 585 | { |
| 586 | AM_DMX_Device_t *dev; |
| 587 | AM_DMX_Filter_t *filter; |
| 588 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 589 | |
| 590 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 591 | |
| 592 | pthread_mutex_lock(&dev->lock); |
| 593 | |
| 594 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 595 | |
| 596 | if (ret == AM_SUCCESS) { |
| 597 | dmx_wait_cb(dev); |
| 598 | ret = dmx_free_filter(dev, filter); |
| 599 | } |
| 600 | |
| 601 | pthread_mutex_unlock(&dev->lock); |
| 602 | |
| 603 | return ret; |
| 604 | } |
| 605 | |
| 606 | /**\brief 让一个过滤器开始运行 |
| 607 | * \param dev_no 解复用设备号 |
| 608 | * \param fhandle 过滤器句柄 |
| 609 | * \return |
| 610 | * - AM_SUCCESS 成功 |
| 611 | * - 其他值 错误代码(见am_dmx.h) |
| 612 | */ |
| 613 | AM_ErrorCode_t AM_DMX_StartFilter(int dev_no, int fhandle) |
| 614 | { |
| 615 | AM_DMX_Device_t *dev; |
| 616 | AM_DMX_Filter_t *filter = NULL; |
| 617 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 618 | |
| 619 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 620 | |
| 621 | pthread_mutex_lock(&dev->lock); |
| 622 | |
| 623 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 624 | |
| 625 | if (!filter->enable) { |
| 626 | if (ret == AM_SUCCESS) { |
| 627 | if (dev->drv->enable_filter) { |
| 628 | ret = dev->drv->enable_filter(dev, filter, AM_TRUE); |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | if (ret == AM_SUCCESS) { |
| 633 | filter->enable = AM_TRUE; |
| 634 | } |
| 635 | } |
| 636 | |
| 637 | pthread_mutex_unlock(&dev->lock); |
| 638 | |
| 639 | return ret; |
| 640 | } |
| 641 | |
| 642 | /**\brief 停止一个过滤器 |
| 643 | * \param dev_no 解复用设备号 |
| 644 | * \param fhandle 过滤器句柄 |
| 645 | * \return |
| 646 | * - AM_SUCCESS 成功 |
| 647 | * - 其他值 错误代码(见am_dmx.h) |
| 648 | */ |
| 649 | AM_ErrorCode_t AM_DMX_StopFilter(int dev_no, int fhandle) |
| 650 | { |
| 651 | AM_DMX_Device_t *dev; |
| 652 | AM_DMX_Filter_t *filter = NULL; |
| 653 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 654 | |
| 655 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 656 | |
| 657 | pthread_mutex_lock(&dev->lock); |
| 658 | |
| 659 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 660 | |
| 661 | if (ret == AM_SUCCESS) { |
| 662 | if (filter->enable) { |
| 663 | dmx_wait_cb(dev); |
| 664 | ret = dmx_stop_filter(dev, filter); |
| 665 | } |
| 666 | } |
| 667 | |
| 668 | pthread_mutex_unlock(&dev->lock); |
| 669 | |
| 670 | return ret; |
| 671 | } |
| 672 | |
| 673 | /**\brief 设置一个过滤器的缓冲区大小 |
| 674 | * \param dev_no 解复用设备号 |
| 675 | * \param fhandle 过滤器句柄 |
| 676 | * \param size 缓冲区大小 |
| 677 | * \return |
| 678 | * - AM_SUCCESS 成功 |
| 679 | * - 其他值 错误代码(见am_dmx.h) |
| 680 | */ |
| 681 | AM_ErrorCode_t AM_DMX_SetBufferSize(int dev_no, int fhandle, int size) |
| 682 | { |
| 683 | AM_DMX_Device_t *dev; |
| 684 | AM_DMX_Filter_t *filter; |
| 685 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 686 | |
| 687 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 688 | |
| 689 | pthread_mutex_lock(&dev->lock); |
| 690 | |
| 691 | if (!dev->drv->set_buf_size) { |
| 692 | printf("do not support set_buf_size"); |
| 693 | ret = AM_DMX_ERR_NOT_SUPPORTED; |
| 694 | } |
| 695 | |
| 696 | if (ret == AM_SUCCESS) |
| 697 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 698 | |
| 699 | if (ret == AM_SUCCESS) |
| 700 | ret = dev->drv->set_buf_size(dev, filter, size); |
| 701 | |
| 702 | pthread_mutex_unlock(&dev->lock); |
| 703 | |
| 704 | return ret; |
| 705 | } |
| 706 | |
| 707 | /**\brief 取得一个过滤器对应的回调函数和用户参数 |
| 708 | * \param dev_no 解复用设备号 |
| 709 | * \param fhandle 过滤器句柄 |
| 710 | * \param[out] cb 返回过滤器对应的回调函数 |
| 711 | * \param[out] data 返回用户参数 |
| 712 | * \return |
| 713 | * - AM_SUCCESS 成功 |
| 714 | * - 其他值 错误代码(见am_dmx.h) |
| 715 | */ |
| 716 | AM_ErrorCode_t AM_DMX_GetCallback(int dev_no, int fhandle, AM_DMX_DataCb *cb, void **data) |
| 717 | { |
| 718 | AM_DMX_Device_t *dev; |
| 719 | AM_DMX_Filter_t *filter; |
| 720 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 721 | |
| 722 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 723 | |
| 724 | pthread_mutex_lock(&dev->lock); |
| 725 | |
| 726 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 727 | |
| 728 | if (ret == AM_SUCCESS) { |
| 729 | if (cb) |
| 730 | *cb = filter->cb; |
| 731 | |
| 732 | if (data) |
| 733 | *data = filter->user_data; |
| 734 | } |
| 735 | |
| 736 | pthread_mutex_unlock(&dev->lock); |
| 737 | |
| 738 | return ret; |
| 739 | } |
| 740 | |
| 741 | /**\brief 设置一个过滤器对应的回调函数和用户参数 |
| 742 | * \param dev_no 解复用设备号 |
| 743 | * \param fhandle 过滤器句柄 |
| 744 | * \param[in] cb 回调函数 |
| 745 | * \param[in] data 回调函数的用户参数 |
| 746 | * \return |
| 747 | * - AM_SUCCESS 成功 |
| 748 | * - 其他值 错误代码(见am_dmx.h) |
| 749 | */ |
| 750 | AM_ErrorCode_t AM_DMX_SetCallback(int dev_no, int fhandle, AM_DMX_DataCb cb, void *data) |
| 751 | { |
| 752 | AM_DMX_Device_t *dev; |
| 753 | AM_DMX_Filter_t *filter; |
| 754 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 755 | |
| 756 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 757 | |
| 758 | pthread_mutex_lock(&dev->lock); |
| 759 | |
| 760 | ret = dmx_get_used_filter(dev, fhandle, &filter); |
| 761 | |
| 762 | if (ret == AM_SUCCESS) { |
| 763 | dmx_wait_cb(dev); |
| 764 | |
| 765 | filter->cb = cb; |
| 766 | filter->user_data = data; |
| 767 | } |
| 768 | |
| 769 | pthread_mutex_unlock(&dev->lock); |
| 770 | |
| 771 | return ret; |
| 772 | } |
| 773 | |
| 774 | /**\brief 设置解复用设备的输入源 |
| 775 | * \param dev_no 解复用设备号 |
| 776 | * \param src 输入源 |
| 777 | * \return |
| 778 | * - AM_SUCCESS 成功 |
| 779 | * - 其他值 错误代码(见am_dmx.h) |
| 780 | */ |
| 781 | AM_ErrorCode_t AM_DMX_SetSource(int dev_no, AM_DMX_Source_t src) |
| 782 | { |
| 783 | AM_DMX_Device_t *dev; |
| 784 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 785 | |
| 786 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 787 | |
| 788 | pthread_mutex_lock(&dev->lock); |
| 789 | if (!dev->drv->set_source) { |
| 790 | printf("do not support set_source"); |
| 791 | ret = AM_DMX_ERR_NOT_SUPPORTED; |
| 792 | } |
| 793 | |
| 794 | if (ret == AM_SUCCESS) { |
| 795 | ret = dev->drv->set_source(dev, src); |
| 796 | } |
| 797 | |
| 798 | pthread_mutex_unlock(&dev->lock); |
| 799 | |
| 800 | if (ret == AM_SUCCESS) { |
| 801 | // pthread_mutex_lock(&am_gAdpLock); |
| 802 | dev->src = src; |
| 803 | // pthread_mutex_unlock(&am_gAdpLock); |
| 804 | } |
| 805 | |
| 806 | return ret; |
| 807 | } |
| 808 | |
| 809 | /**\brief DMX同步,可用于等待回调函数执行完毕 |
| 810 | * \param dev_no 解复用设备号 |
| 811 | * \return |
| 812 | * - AM_SUCCESS 成功 |
| 813 | * - 其他值 错误代码(见am_dmx.h) |
| 814 | */ |
| 815 | AM_ErrorCode_t AM_DMX_Sync(int dev_no) |
| 816 | { |
| 817 | AM_DMX_Device_t *dev; |
| 818 | AM_ErrorCode_t ret = AM_SUCCESS; |
| 819 | |
| 820 | AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| 821 | |
| 822 | pthread_mutex_lock(&dev->lock); |
| 823 | if (dev->thread != pthread_self()) { |
| 824 | while (dev->flags & DMX_FL_RUN_CB) |
| 825 | pthread_cond_wait(&dev->cond, &dev->lock); |
| 826 | } |
| 827 | pthread_mutex_unlock(&dev->lock); |
| 828 | |
| 829 | return ret; |
| 830 | } |
| 831 | |
| 832 | AM_ErrorCode_t AM_DMX_GetScrambleStatus(int dev_no, AM_Bool_t dev_status[2]) |
| 833 | { |
| 834 | #if 0 |
| 835 | char buf[32]; |
| 836 | char class_file[64]; |
| 837 | int vflag, aflag; |
| 838 | int i; |
| 839 | |
| 840 | dev_status[0] = dev_status[1] = AM_FALSE; |
| 841 | snprintf(class_file, sizeof(class_file), "/sys/class/dmx/demux%d_scramble", dev_no); |
| 842 | for (i = 0; i < 5; i++) { |
| 843 | if (AM_FileRead(class_file, buf, sizeof(buf)) == AM_SUCCESS) { |
| 844 | sscanf(buf, "%d %d", &vflag, &aflag); |
| 845 | if (!dev_status[0]) |
| 846 | dev_status[0] = vflag ? AM_TRUE : AM_FALSE; |
| 847 | if (!dev_status[1]) |
| 848 | dev_status[1] = aflag ? AM_TRUE : AM_FALSE; |
| 849 | // AM_DEBUG(1, "AM_DMX_GetScrambleStatus video scramble %d, audio scramble %d\n", vflag, aflag); |
| 850 | if (dev_status[0] && dev_status[1]) { |
| 851 | return AM_SUCCESS; |
| 852 | } |
| 853 | usleep(10 * 1000); |
| 854 | } else { |
| 855 | printf("AM_DMX_GetScrambleStatus read scramble status failed\n"); |
| 856 | return AM_FAILURE; |
| 857 | } |
| 858 | } |
| 859 | #endif |
| 860 | return AM_SUCCESS; |
| 861 | } |
| 862 | |
| 863 | |