bitstreamfeeder.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. //--=========================================================================--
  2. // This file is a part of VPU Reference API project
  3. //-----------------------------------------------------------------------------
  4. //
  5. // This confidential and proprietary software may be used only
  6. // as authorized by a licensing agreement from Chips&Media Inc.
  7. // In the event of publication, the following notice is applicable:
  8. //
  9. // (C) COPYRIGHT CHIPS&MEDIA INC.
  10. // ALL RIGHTS RESERVED
  11. //
  12. // The entire notice above must be reproduced on all authorized
  13. // copies.
  14. //
  15. //--=========================================================================--
  16. #include <stdio.h>
  17. #include <stdarg.h>
  18. #include <time.h>
  19. #include "vpuapifunc.h"
  20. #include "main_helper.h"
  21. typedef struct {
  22. FeedingMethod method;
  23. Uint8* remainData;
  24. Uint32 remainDataSize;
  25. void* actualFeeder;
  26. PhysicalAddress base;
  27. Uint32 size;
  28. Uint32 fillingMode;
  29. BOOL eos;
  30. VpuThread threadHandle;
  31. DecHandle decHandle;
  32. EndianMode endian;
  33. BSFeederHook observer;
  34. void* observerArg;
  35. BOOL autoUpdate; /* TRUE - Call VPU_DecUpdateBitstreamBuffer() in the bitstream feeder. default */
  36. } BitstreamFeeder;
  37. static void BitstreamFeeder_DummyObserver(
  38. void* handle,
  39. void* es,
  40. Uint32 size,
  41. void* arg
  42. )
  43. {
  44. UNREFERENCED_PARAMETER(handle);
  45. UNREFERENCED_PARAMETER(es);
  46. UNREFERENCED_PARAMETER(size);
  47. UNREFERENCED_PARAMETER(arg);
  48. }
  49. extern void* BSFeederFixedSize_Create(
  50. const char* path,
  51. Uint32 chunkSize
  52. );
  53. extern BOOL BSFeederFixedSize_Destroy(
  54. BSFeeder feeder
  55. );
  56. extern Int32 BSFeederFixedSize_Act(
  57. void* feeder,
  58. BSChunk* chunk
  59. );
  60. extern Int32 BSFeederFixedSize_Rewind(
  61. void* feeder
  62. );
  63. extern void* BSFeederFrameSize_Create(
  64. const char* path,
  65. CodStd codec,
  66. CodStd* retCodecId,
  67. Uint32* retMp4ClassId,
  68. Uint32* retSeqWidth,
  69. Uint32* retSeqHeight
  70. );
  71. extern BOOL BSFeederFrameSize_Destroy(
  72. void* feeder
  73. );
  74. extern Int32 BSFeederFrameSize_Act(
  75. void* feeder,
  76. BSChunk* packet
  77. );
  78. #ifdef SUPPORT_FFMPEG_DEMUX
  79. extern BOOL BSFeederFrameSize_Rewind(
  80. void* feeder
  81. );
  82. #endif
  83. extern void* BSFeederSizePlusEs_Create(
  84. const char* path
  85. );
  86. extern BOOL BSFeederSizePlusEs_Destroy(
  87. void* feeder
  88. );
  89. extern Int32 BSFeederSizePlusEs_Act(
  90. void* feeder,
  91. BSChunk* chunk
  92. );
  93. extern Int32 BSFeederSizePlusEs_Rewind(
  94. void* feeder
  95. );
  96. /**
  97. * Abstract Bitstream Feeader Functions
  98. */
  99. void* BitstreamFeeder_Create(
  100. const char* path,
  101. FeedingMethod method,
  102. PhysicalAddress base,
  103. Uint32 size,
  104. ...
  105. )
  106. {
  107. /*lint -esym(438, ap) */
  108. va_list ap;
  109. Uint32 chunkSize;
  110. BitstreamFeeder* handle = NULL;
  111. void* feeder = NULL;
  112. CodStd codecId;
  113. CodStd* retCodecId;
  114. Uint32* retMp4ClassId;
  115. Uint32* retSeqWidth;
  116. Uint32* retSeqHeight;
  117. switch (method) {
  118. case FEEDING_METHOD_FIXED_SIZE:
  119. va_start(ap, size);
  120. chunkSize = va_arg(ap, int);
  121. va_end(ap);
  122. feeder = BSFeederFixedSize_Create(path, chunkSize);
  123. break;
  124. case FEEDING_METHOD_FRAME_SIZE:
  125. va_start(ap, size);
  126. codecId = (CodStd)va_arg(ap, Int32);
  127. retCodecId = (CodStd*)va_arg(ap, CodStd*);
  128. retMp4ClassId = (Uint32*)va_arg(ap, Uint32*);
  129. retSeqWidth = (Uint32*)va_arg(ap, Uint32*);
  130. retSeqHeight = (Uint32*)va_arg(ap, Uint32*);
  131. va_end(ap);
  132. feeder = BSFeederFrameSize_Create(path, codecId, retCodecId, retMp4ClassId, retSeqWidth, retSeqHeight);
  133. break;
  134. case FEEDING_METHOD_SIZE_PLUS_ES:
  135. feeder = BSFeederSizePlusEs_Create(path);
  136. break;
  137. default:
  138. feeder = NULL;
  139. break;
  140. }
  141. if (feeder != NULL) {
  142. if ((handle=(BitstreamFeeder*)osal_malloc(sizeof(BitstreamFeeder))) == NULL) {
  143. VLOG(ERR, "%s:%d Failed to allocate memory\n", __FUNCTION__, __LINE__);
  144. return NULL;
  145. }
  146. handle->actualFeeder = feeder;
  147. handle->method = method;
  148. handle->remainData = NULL;
  149. handle->remainDataSize = 0;
  150. handle->base = base;
  151. handle->size = size;
  152. handle->fillingMode = (method == FEEDING_METHOD_FIXED_SIZE) ? BSF_FILLING_RINGBUFFER : BSF_FILLING_LINEBUFFER;
  153. handle->threadHandle = NULL;
  154. handle->eos = FALSE;
  155. handle->observer = (BSFeederHook)BitstreamFeeder_DummyObserver;
  156. handle->observerArg = NULL;
  157. handle->autoUpdate = TRUE;
  158. }
  159. return handle;
  160. /*lint +esym(438, ap) */
  161. }
  162. void BitstreamFeeder_SetFillMode(
  163. BSFeeder feeder,
  164. Uint32 mode
  165. )
  166. {
  167. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  168. switch (mode) {
  169. case BSF_FILLING_AUTO:
  170. bsf->fillingMode = (bsf->method == FEEDING_METHOD_FIXED_SIZE) ? BSF_FILLING_RINGBUFFER : BSF_FILLING_LINEBUFFER;
  171. break;
  172. case BSF_FILLING_RINGBUFFER:
  173. case BSF_FILLING_LINEBUFFER:
  174. case BSF_FILLING_RINGBUFFER_WITH_ENDFLAG:
  175. bsf->fillingMode = mode;
  176. break;
  177. default:
  178. VLOG(INFO, "%s Not supported mode %d\n", __FUNCTION__, mode);
  179. break;
  180. }
  181. }
  182. static Uint32 FeedBitstream(
  183. BSFeeder feeder,
  184. vpu_buffer_t* buffer
  185. )
  186. {
  187. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  188. Int32 feedingSize = 0;
  189. BSChunk chunk = {0};
  190. PhysicalAddress rdPtr, wrPtr;
  191. Uint32 room;
  192. DecHandle decHandle;
  193. EndianMode endian;
  194. if (bsf == NULL) {
  195. VLOG(ERR, "%s:%d Null handle\n", __FUNCTION__, __LINE__);
  196. return 0;
  197. }
  198. decHandle = bsf->decHandle;
  199. endian = bsf->endian;
  200. if (bsf->remainData == NULL) {
  201. chunk.size = bsf->size;
  202. chunk.data = osal_malloc(chunk.size);
  203. chunk.eos = FALSE;
  204. if (chunk.data == NULL) {
  205. VLOG(ERR, "%s:%d failed to allocate memory\n", __FUNCTION__, __LINE__);
  206. return 0;
  207. }
  208. switch (bsf->method) {
  209. case FEEDING_METHOD_FIXED_SIZE:
  210. feedingSize = BSFeederFixedSize_Act(bsf->actualFeeder, &chunk);
  211. break;
  212. case FEEDING_METHOD_FRAME_SIZE:
  213. feedingSize = BSFeederFrameSize_Act(bsf->actualFeeder, &chunk);
  214. break;
  215. case FEEDING_METHOD_SIZE_PLUS_ES:
  216. feedingSize = BSFeederSizePlusEs_Act(bsf->actualFeeder, &chunk);
  217. break;
  218. default:
  219. VLOG(ERR, "%s:%d Invalid method(%d)\n", __FUNCTION__, __LINE__, bsf->method);
  220. osal_free(chunk.data);
  221. return 0;
  222. }
  223. }
  224. else {
  225. chunk.data = bsf->remainData;
  226. feedingSize = bsf->remainDataSize;
  227. }
  228. bsf->observer((void*)bsf, chunk.data, feedingSize, bsf->observerArg);
  229. if (feedingSize < 0) {
  230. VLOG(ERR, "feeding size is negative value: %d\n", feedingSize);
  231. osal_free(chunk.data);
  232. return 0;
  233. }
  234. if (feedingSize > 0) {
  235. Uint32 coreIdx = VPU_HANDLE_CORE_INDEX(decHandle);
  236. Uint32 rightSize=0, leftSize=feedingSize;
  237. if (buffer == NULL) {
  238. VPU_DecGetBitstreamBuffer(decHandle, &rdPtr, &wrPtr, &room);
  239. }
  240. else {
  241. rdPtr = wrPtr = buffer->phys_addr;
  242. room = buffer->size;
  243. }
  244. if ((Int32)room < feedingSize) {
  245. bsf->remainData = chunk.data;
  246. bsf->remainDataSize = feedingSize;
  247. return 0;
  248. }
  249. if (bsf->fillingMode == BSF_FILLING_RINGBUFFER || bsf->fillingMode == BSF_FILLING_RINGBUFFER_WITH_ENDFLAG) {
  250. if ((wrPtr+feedingSize) >= (bsf->base+bsf->size)) {
  251. PhysicalAddress endAddr = bsf->base+bsf->size;
  252. rightSize = endAddr-wrPtr;
  253. leftSize = (wrPtr+feedingSize) - endAddr;
  254. if (rightSize > 0) {
  255. VpuWriteMem(coreIdx, wrPtr, (unsigned char*)chunk.data, rightSize, (int)endian);
  256. }
  257. wrPtr = bsf->base;
  258. }
  259. }
  260. VpuWriteMem(coreIdx, wrPtr, (unsigned char*)chunk.data+rightSize, leftSize, (int)endian);
  261. }
  262. if (bsf->autoUpdate == TRUE) {
  263. /* If feedingSize is equal to zero then VPU will be ready to terminate current sequence. */
  264. VPU_DecUpdateBitstreamBuffer(decHandle, feedingSize);
  265. if (chunk.eos == TRUE || bsf->fillingMode == BSF_FILLING_RINGBUFFER_WITH_ENDFLAG) {
  266. VPU_DecUpdateBitstreamBuffer(decHandle, STREAM_END_SET_FLAG);
  267. }
  268. }
  269. bsf->eos = chunk.eos;
  270. osal_free(chunk.data);
  271. bsf->remainData = NULL;
  272. bsf->remainDataSize = 0;
  273. return feedingSize;
  274. }
  275. static void FeederThread(
  276. void* arg
  277. )
  278. {
  279. BitstreamFeeder* bsf = (BitstreamFeeder*)arg;
  280. while (bsf->eos == FALSE) {
  281. MSleep(10);
  282. FeedBitstream(bsf, NULL);
  283. }
  284. }
  285. Uint32 BitstreamFeeder_Act(
  286. DecHandle decHandle,
  287. BSFeeder feeder,
  288. EndianMode endian,
  289. vpu_buffer_t* buffer
  290. )
  291. {
  292. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  293. bsf->decHandle = decHandle;
  294. bsf->endian = endian;
  295. return FeedBitstream(feeder, buffer);
  296. }
  297. /* \param sync FALSE: The thread fill bitstream into a bitstream buffer continously
  298. * TRUE: The thread start to fill bitstream into a bitstream buffer just one time.
  299. * Client MUST call BitstreamFeeder_Run() with fourth parameter TRUE for every
  300. * decoding sequence.
  301. */
  302. BOOL BitstreamFeeder_Run(
  303. DecHandle decHandle,
  304. BSFeeder feeder,
  305. EndianMode endian
  306. )
  307. {
  308. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  309. VpuThreadRunner runner = (VpuThreadRunner)FeederThread;
  310. bsf->decHandle = decHandle;
  311. bsf->endian = endian;
  312. bsf->threadHandle = VpuThread_Create(runner, (void*)bsf);
  313. if (bsf->threadHandle == NULL) {
  314. return FALSE;
  315. }
  316. return TRUE;
  317. }
  318. BOOL BitstreamFeeder_IsEos(
  319. BSFeeder feeder
  320. )
  321. {
  322. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  323. if (bsf == NULL) {
  324. VLOG(ERR, "%s:%d Null handle\n", __FUNCTION__, __LINE__);
  325. return FALSE;
  326. }
  327. return bsf->eos;
  328. }
  329. void BitstreamFeeder_Stop(
  330. BSFeeder feeder
  331. )
  332. {
  333. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  334. if (bsf == NULL) {
  335. VLOG(ERR, "%s:%d Null handle\n", __FUNCTION__, __LINE__);
  336. return;
  337. }
  338. if (bsf->threadHandle != NULL) {
  339. bsf->eos = TRUE;
  340. VpuThread_Join(bsf->threadHandle);
  341. bsf->threadHandle = NULL;
  342. }
  343. }
  344. BOOL BitstreamFeeder_Destroy(
  345. BSFeeder feeder
  346. )
  347. {
  348. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  349. if (bsf == NULL) {
  350. VLOG(ERR, "%s:%d Null handle\n", __FUNCTION__, __LINE__);
  351. return FALSE;
  352. }
  353. if (bsf->threadHandle) {
  354. bsf->eos = TRUE;
  355. VpuThread_Join(bsf->threadHandle);
  356. bsf->threadHandle = NULL;
  357. }
  358. switch (bsf->method) {
  359. case FEEDING_METHOD_FIXED_SIZE:
  360. BSFeederFixedSize_Destroy(bsf->actualFeeder);
  361. break;
  362. case FEEDING_METHOD_FRAME_SIZE:
  363. BSFeederFrameSize_Destroy(bsf->actualFeeder);
  364. break;
  365. case FEEDING_METHOD_SIZE_PLUS_ES:
  366. BSFeederSizePlusEs_Destroy(bsf->actualFeeder);
  367. break;
  368. default:
  369. VLOG(ERR, "%s:%d Invalid method(%d)\n", __FUNCTION__, __LINE__, bsf->method);
  370. break;
  371. }
  372. if (bsf->remainData) {
  373. osal_free(bsf->remainData);
  374. }
  375. osal_free(bsf);
  376. return TRUE;
  377. }
  378. BOOL BitstreamFeeder_Rewind(
  379. BSFeeder feeder
  380. )
  381. {
  382. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  383. BOOL success = FALSE;
  384. if (bsf == NULL) {
  385. VLOG(ERR, "%s:%d handle is NULL\n", __FUNCTION__, __LINE__);
  386. return success;
  387. }
  388. switch (bsf->method) {
  389. case FEEDING_METHOD_FIXED_SIZE:
  390. success = BSFeederFixedSize_Rewind(bsf->actualFeeder);
  391. break;
  392. #ifdef SUPPORT_FFMPEG_DEMUX
  393. case FEEDING_METHOD_FRAME_SIZE:
  394. success = BSFeederFrameSize_Rewind(bsf->actualFeeder);
  395. break;
  396. #endif
  397. case FEEDING_METHOD_SIZE_PLUS_ES:
  398. success = BSFeederSizePlusEs_Rewind(bsf->actualFeeder);
  399. break;
  400. default:
  401. VLOG(ERR, "%s:%d Invalid method(%d)\n", __FUNCTION__, __LINE__, bsf->method);
  402. break;
  403. }
  404. if (success == TRUE) {
  405. bsf->eos = FALSE;
  406. }
  407. return success;
  408. }
  409. BOOL BitstreamFeeder_SetHook(
  410. BSFeeder feeder,
  411. BSFeederHook hookFunc,
  412. void* hookArg
  413. )
  414. {
  415. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  416. if (bsf == NULL) {
  417. VLOG(ERR, "%s:%d handle is NULL\n", __FUNCTION__, __LINE__);
  418. return FALSE;
  419. }
  420. if (hookFunc == NULL) {
  421. bsf->observer = (BSFeederHook)BitstreamFeeder_DummyObserver;
  422. }
  423. else {
  424. bsf->observer = hookFunc;
  425. }
  426. bsf->observerArg = hookArg;
  427. return TRUE;
  428. }
  429. BOOL BitstreamFeeder_SetAutoUpdate(
  430. BSFeeder feeder,
  431. BOOL onoff
  432. )
  433. {
  434. BitstreamFeeder* bsf = (BitstreamFeeder*)feeder;
  435. if (bsf == NULL) {
  436. VLOG(ERR, "%s:%d handle is NULL\n", __FUNCTION__, __LINE__);
  437. return FALSE;
  438. }
  439. bsf->autoUpdate = onoff;
  440. return TRUE;
  441. }