bitstreamfeeder.c 13 KB

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