luat_lib_multimedia_codec.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. @module codec
  3. @summary 多媒体-编解码
  4. @version 1.0
  5. @date 2022.03.11
  6. @demo multimedia
  7. @tag LUAT_USE_MEDIA
  8. */
  9. #include "luat_base.h"
  10. #include "luat_multimedia.h"
  11. #include "luat_msgbus.h"
  12. #include "luat_zbuff.h"
  13. #include "luat_fs.h"
  14. #include "luat_mem.h"
  15. #define LUAT_LOG_TAG "codec"
  16. #include "luat_log.h"
  17. #ifdef LUAT_SUPPORT_AMR
  18. #include "interf_enc.h"
  19. #include "interf_dec.h"
  20. #endif
  21. #ifndef MINIMP3_MAX_SAMPLES_PER_FRAME
  22. #define MINIMP3_MAX_SAMPLES_PER_FRAME (2*1152)
  23. #endif
  24. /**
  25. 创建编解码用的codec
  26. @api codec.create(type, isDecoder, quality)
  27. @int 多媒体类型,目前支持codec.MP3 codec.AMR
  28. @boolean 是否是解码器,true解码器,false编码器,默认true,是解码器
  29. @int 编码等级,部分bsp有内部编解码器,可能需要提前输入编解码等级,不知道的就填7
  30. @return userdata 成功返回一个数据结构,否则返回nil
  31. @usage
  32. -- 创建解码器
  33. local decoder = codec.create(codec.MP3)--创建一个mp3的decoder
  34. -- 创建编码器
  35. local encoder = codec.create(codec.AMR, false)--创建一个amr的encoder
  36. -- 创建编码器
  37. local encoder = codec.create(codec.AMR_WB, false, 8)--创建一个amr-wb的encoder,编码等级默认8
  38. */
  39. static int l_codec_create(lua_State *L) {
  40. uint8_t type = luaL_optinteger(L, 1, LUAT_MULTIMEDIA_DATA_TYPE_MP3);
  41. uint8_t is_decoder = 1;
  42. if (lua_isboolean(L, 2)) {
  43. is_decoder = lua_toboolean(L, 2);
  44. }
  45. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)lua_newuserdata(L, sizeof(luat_multimedia_codec_t));
  46. if (coder == NULL) {
  47. lua_pushnil(L);
  48. } else {
  49. memset(coder, 0, sizeof(luat_multimedia_codec_t));
  50. coder->type = type;
  51. coder->is_decoder = is_decoder;
  52. if (is_decoder)
  53. {
  54. switch (type) {
  55. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  56. coder->mp3_decoder = mp3_decoder_create();
  57. if (!coder->mp3_decoder) {
  58. lua_pushnil(L);
  59. return 1;
  60. }
  61. break;
  62. }
  63. }
  64. else
  65. {
  66. switch (type) {
  67. #ifdef LUAT_SUPPORT_AMR
  68. #ifdef LUAT_USE_INTER_AMR
  69. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  70. coder->amr_coder = luat_audio_inter_amr_coder_init(0, luaL_optinteger(L, 3, 7));
  71. if (!coder->amr_coder) {
  72. lua_pushnil(L);
  73. return 1;
  74. }
  75. break;
  76. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  77. coder->amr_coder = luat_audio_inter_amr_coder_init(1, luaL_optinteger(L, 3, 8));
  78. if (!coder->amr_coder) {
  79. lua_pushnil(L);
  80. return 1;
  81. }
  82. break;
  83. #else
  84. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  85. coder->amr_coder = Encoder_Interface_init(0);
  86. if (!coder->amr_coder) {
  87. lua_pushnil(L);
  88. return 1;
  89. }
  90. break;
  91. #endif
  92. #endif
  93. default:
  94. lua_pushnil(L);
  95. return 1;
  96. }
  97. }
  98. luaL_setmetatable(L, LUAT_M_CODE_TYPE);
  99. }
  100. return 1;
  101. }
  102. /**
  103. decoder从文件中解析出音频信息
  104. @api codec.info(decoder, file_path)
  105. @userdata 解码用的decoder
  106. @string 文件路径
  107. @return boolean 是否成功解析
  108. @return int 音频格式
  109. @return int 声音通道数
  110. @return int 采样频率
  111. @return int 采样位数
  112. @return boolean 是否有符号
  113. @usage
  114. local result, audio_format, num_channels, sample_rate, bits_per_sample, is_signed= codec.info(coder, "xxx")
  115. */
  116. static int l_codec_get_audio_info(lua_State *L) {
  117. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  118. uint32_t jump, i;
  119. uint8_t temp[16];
  120. int result = 0;
  121. int audio_format = LUAT_MULTIMEDIA_DATA_TYPE_NONE;
  122. uint8_t num_channels;
  123. uint32_t sample_rate;
  124. int bits_per_sample = 16;
  125. uint32_t align;
  126. int is_signed = 1;
  127. size_t len;
  128. const char *file_path = luaL_checklstring(L, 2, &len);
  129. FILE *fd = luat_fs_fopen(file_path, "r");
  130. if (fd && coder)
  131. {
  132. switch(coder->type)
  133. {
  134. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  135. mp3_decoder_init(coder->mp3_decoder);
  136. coder->buff.addr = luat_heap_malloc(MP3_FRAME_LEN);
  137. coder->buff.len = MP3_FRAME_LEN;
  138. coder->buff.used = luat_fs_fread(temp, 10, 1, fd);
  139. if (coder->buff.used != 10)
  140. {
  141. break;
  142. }
  143. if (!memcmp(temp, "ID3", 3))
  144. {
  145. jump = 0;
  146. for(i = 0; i < 4; i++)
  147. {
  148. jump <<= 7;
  149. jump |= temp[6 + i] & 0x7f;
  150. }
  151. // LLOGD("jump head %d", jump);
  152. luat_fs_fseek(fd, jump, SEEK_SET);
  153. }
  154. coder->buff.used = luat_fs_fread(coder->buff.addr, MP3_FRAME_LEN, 1, fd);
  155. result = mp3_decoder_get_info(coder->mp3_decoder, coder->buff.addr, coder->buff.used, &sample_rate, &num_channels);
  156. mp3_decoder_init(coder->mp3_decoder);
  157. audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
  158. break;
  159. case LUAT_MULTIMEDIA_DATA_TYPE_WAV:
  160. luat_fs_fread(temp, 12, 1, fd);
  161. if (!memcmp(temp, "RIFF", 4) || !memcmp(temp + 8, "WAVE", 4))
  162. {
  163. luat_fs_fread(temp, 8, 1, fd);
  164. if (!memcmp(temp, "fmt ", 4))
  165. {
  166. memcpy(&len, temp + 4, 4);
  167. coder->buff.addr = luat_heap_malloc(len);
  168. luat_fs_fread(coder->buff.addr, len, 1, fd);
  169. audio_format = coder->buff.addr[0];
  170. num_channels = coder->buff.addr[2];
  171. memcpy(&sample_rate, coder->buff.addr + 4, 4);
  172. align = coder->buff.addr[12];
  173. bits_per_sample = coder->buff.addr[14];
  174. coder->read_len = (align * sample_rate >> 3) & ~(3);
  175. // LLOGD("size %d", coder->read_len);
  176. luat_heap_free(coder->buff.addr);
  177. coder->buff.addr = NULL;
  178. luat_fs_fread(temp, 8, 1, fd);
  179. if (!memcmp(temp, "fact", 4))
  180. {
  181. memcpy(&len, temp + 4, 4);
  182. luat_fs_fseek(fd, len, SEEK_CUR);
  183. luat_fs_fread(temp, 8, 1, fd);
  184. }
  185. if (!memcmp(temp, "data", 4))
  186. {
  187. result = 1;
  188. }
  189. else
  190. {
  191. LLOGD("no data");
  192. result = 0;
  193. }
  194. }
  195. else
  196. {
  197. LLOGD("no fmt");
  198. }
  199. }
  200. else
  201. {
  202. LLOGD("head error");
  203. }
  204. break;
  205. default:
  206. break;
  207. }
  208. }
  209. if (!result)
  210. {
  211. luat_fs_fclose(fd);
  212. }
  213. else
  214. {
  215. coder->fd = fd;
  216. }
  217. lua_pushboolean(L, result);
  218. lua_pushinteger(L, audio_format);
  219. lua_pushinteger(L, num_channels);
  220. lua_pushinteger(L, sample_rate);
  221. lua_pushinteger(L, bits_per_sample);
  222. lua_pushboolean(L, is_signed);
  223. return 6;
  224. }
  225. /**
  226. decoder从文件中解析出原始音频数据,比如从MP3文件里解析出PCM数据,这里的文件路径已经在codec.info传入,不需要再次传入
  227. @api codec.data(decoder, out_buff)
  228. @userdata 解码用的decoder
  229. @zbuff 存放输出数据的zbuff,空间必须不少于16KB
  230. @int 最少解码出多少字节的音频数据,默认16384
  231. @return boolean 是否成功解析
  232. @usage
  233. -- 大内存设备
  234. local buff = zbuff.create(16*1024)
  235. local result = codec.data(coder, buff)
  236. -- 小内存设备
  237. local buff = zbuff.create(8*1024)
  238. local result = codec.data(coder, buff, 4096)
  239. */
  240. static int l_codec_get_audio_data(lua_State *L) {
  241. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  242. uint32_t pos = 0;
  243. int read_len;
  244. int result = 0;
  245. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  246. uint32_t is_not_end = 1;
  247. uint32_t hz, out_len, used;
  248. size_t mini_output = luaL_optinteger(L, 3, 16384);
  249. if (mini_output > 16384)
  250. mini_output = 16384;
  251. else if (mini_output < 4 * 1024)
  252. mini_output = 4 * 1024;
  253. out_buff->used = 0;
  254. if (coder)
  255. {
  256. switch(coder->type)
  257. {
  258. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  259. GET_MP3_DATA:
  260. if (coder->buff.used < MINIMP3_MAX_SAMPLES_PER_FRAME)
  261. {
  262. read_len = luat_fs_fread((void*)(coder->buff.addr + coder->buff.used), MINIMP3_MAX_SAMPLES_PER_FRAME, 1, coder->fd);
  263. if (read_len > 0)
  264. {
  265. coder->buff.used += read_len;
  266. }
  267. else
  268. {
  269. is_not_end = 0;
  270. }
  271. }
  272. do
  273. {
  274. result = mp3_decoder_get_data(coder->mp3_decoder, coder->buff.addr + pos, coder->buff.used - pos, out_buff->addr + out_buff->used, &out_len, &hz, &used);
  275. if (result > 0)
  276. {
  277. out_buff->used += out_len;
  278. }
  279. if (result < 0) {
  280. return 0;
  281. }
  282. // if (!result) {
  283. // LLOGD("jump %dbyte", info.frame_bytes);
  284. // }
  285. pos += used;
  286. if ((out_buff->len - out_buff->used) < (MINIMP3_MAX_SAMPLES_PER_FRAME * 2))
  287. {
  288. break;
  289. }
  290. } while ((coder->buff.used - pos) >= (MINIMP3_MAX_SAMPLES_PER_FRAME * is_not_end + 1));
  291. // LLOGD("result %u,%u,%u,%u,%u", result, out_buff->used, coder->buff.used, pos, info.frame_bytes);
  292. if (pos >= coder->buff.used)
  293. {
  294. coder->buff.used = 0;
  295. }
  296. else
  297. {
  298. memmove(coder->buff.addr, coder->buff.addr + pos, coder->buff.used - pos);
  299. coder->buff.used -= pos;
  300. }
  301. pos = 0;
  302. if (!out_buff->used)
  303. {
  304. if (is_not_end)
  305. {
  306. goto GET_MP3_DATA;
  307. }
  308. else
  309. {
  310. result = 0;
  311. }
  312. }
  313. else
  314. {
  315. if ((out_buff->used < mini_output) && is_not_end)
  316. {
  317. goto GET_MP3_DATA;
  318. }
  319. result = 1;
  320. }
  321. break;
  322. case LUAT_MULTIMEDIA_DATA_TYPE_WAV:
  323. read_len = luat_fs_fread(out_buff->addr + out_buff->used, coder->read_len, 1, coder->fd);
  324. if (read_len > 0)
  325. {
  326. out_buff->used += read_len;
  327. result = 1;
  328. }
  329. else
  330. {
  331. result = 0;
  332. }
  333. break;
  334. default:
  335. break;
  336. }
  337. }
  338. lua_pushboolean(L, result);
  339. return 1;
  340. }
  341. /**
  342. 编码音频数据,由于flash和ram空间一般比较有限,除了部分bsp有内部amr编码功能,目前只支持amr-nb编码
  343. @api codec.encode(coder, in_buffer, out_buffer, mode)
  344. @userdata codec.create创建的编解码用的coder
  345. @zbuff 输入的数据,zbuff形式,从0到used
  346. @zbuff 输出的数据,zbuff形式,自动添加到buff的尾部,如果空间大小不足,会自动扩展,但是会额外消耗时间,甚至会失败,所以尽量一开始就给足空间
  347. @int amr_nb的编码等级 0~7(即 MR475~MR122)值越大消耗的空间越多,音质越高,默认0 amr_wb的编码等级 0~8,值越大消耗的空间越多,音质越高,默认0
  348. @return boolean 成功返回true,失败返回false
  349. @usage
  350. codec.encode(amr_coder, inbuf, outbuf, codec.AMR_)
  351. */
  352. static int l_codec_encode_audio_data(lua_State *L) {
  353. #ifdef LUAT_SUPPORT_AMR
  354. #ifdef LUAT_USE_INTER_AMR
  355. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  356. luat_zbuff_t *in_buff;
  357. if (luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)){
  358. in_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  359. }else{
  360. in_buff = ((luat_zbuff_t *)lua_touserdata(L, 2));
  361. }
  362. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  363. if (!coder || !in_buff || !out_buff || (coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB && coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB) || coder->is_decoder)
  364. {
  365. lua_pushboolean(L, 0);
  366. return 1;
  367. }
  368. uint8_t outbuf[128];
  369. int16_t *pcm = (int16_t *)in_buff->addr;
  370. uint32_t total_len = in_buff->used >> 1;
  371. uint32_t done_len = 0;
  372. uint32_t pcm_len = (coder->type - LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB + 1) * 160;
  373. uint8_t out_len;
  374. while ((total_len - done_len) >= pcm_len)
  375. {
  376. luat_audio_inter_amr_coder_encode(coder->amr_coder, &pcm[done_len], outbuf, &out_len);
  377. if (out_len <= 0)
  378. {
  379. LLOGE("encode error in %d,result %d", done_len, out_len);
  380. }
  381. else
  382. {
  383. if ((out_buff->len - out_buff->used) < out_len)
  384. {
  385. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len))
  386. {
  387. lua_pushboolean(L, 0);
  388. return 1;
  389. }
  390. }
  391. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  392. out_buff->used += out_len;
  393. }
  394. done_len += pcm_len;
  395. }
  396. lua_pushboolean(L, 1);
  397. return 1;
  398. #else
  399. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  400. luat_zbuff_t *in_buff;
  401. if (luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)){
  402. in_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  403. }else{
  404. in_buff = ((luat_zbuff_t *)lua_touserdata(L, 2));
  405. }
  406. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  407. int mode = luaL_optinteger(L, 4, MR475);
  408. if (!coder || !in_buff || !out_buff || (coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB) || coder->is_decoder)
  409. {
  410. lua_pushboolean(L, 0);
  411. return 1;
  412. }
  413. if (mode > MR122)
  414. {
  415. mode = MR475;
  416. }
  417. uint8_t outbuf[64];
  418. int16_t *pcm = (int16_t *)in_buff->addr;
  419. uint32_t total_len = in_buff->used >> 1;
  420. uint32_t done_len = 0;
  421. int out_len;
  422. while ((total_len - done_len) >= 160)
  423. {
  424. out_len = Encoder_Interface_Encode(coder->amr_coder, mode, &pcm[done_len], outbuf, 0);
  425. if (out_len <= 0)
  426. {
  427. LLOGE("encode error in %d,result %d", done_len, out_len);
  428. }
  429. else
  430. {
  431. if ((out_buff->len - out_buff->used) < out_len)
  432. {
  433. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len))
  434. {
  435. lua_pushboolean(L, 0);
  436. return 1;
  437. }
  438. }
  439. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  440. out_buff->used += out_len;
  441. }
  442. done_len += 160;
  443. }
  444. lua_pushboolean(L, 1);
  445. return 1;
  446. #endif
  447. #else
  448. lua_pushboolean(L, 0);
  449. return 1;
  450. #endif
  451. }
  452. static int l_codec_gc(lua_State *L)
  453. {
  454. luat_multimedia_codec_t *coder = ((luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE));
  455. if (coder->fd) {
  456. luat_fs_fclose(coder->fd);
  457. coder->fd = NULL;
  458. }
  459. if (coder->buff.addr)
  460. {
  461. luat_heap_free(coder->buff.addr);
  462. coder->buff.addr = NULL;
  463. memset(&coder->buff, 0, sizeof(luat_zbuff_t));
  464. }
  465. switch(coder->type) {
  466. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  467. if (coder->is_decoder && coder->mp3_decoder) {
  468. luat_heap_free(coder->mp3_decoder);
  469. coder->mp3_decoder = NULL;
  470. }
  471. break;
  472. #ifdef LUAT_SUPPORT_AMR
  473. #ifdef LUAT_USE_INTER_AMR
  474. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  475. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  476. if (!coder->is_decoder && coder->amr_coder) {
  477. luat_audio_inter_amr_coder_deinit(coder->amr_coder);
  478. coder->amr_coder = NULL;
  479. }
  480. break;
  481. #else
  482. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  483. if (!coder->is_decoder && coder->amr_coder) {
  484. Encoder_Interface_exit(coder->amr_coder);
  485. coder->amr_coder = NULL;
  486. }
  487. break;
  488. #endif
  489. #endif
  490. }
  491. return 0;
  492. }
  493. /**
  494. 释放编解码用的coder
  495. @api codec.release(coder)
  496. @coder codec.create创建的编解码用的coder
  497. @usage
  498. codec.release(coder)
  499. */
  500. static int l_codec_release(lua_State *L) {
  501. return l_codec_gc(L);
  502. }
  503. static const rotable_Reg_t reg_codec[] =
  504. {
  505. { "create" , ROREG_FUNC(l_codec_create)},
  506. { "info" , ROREG_FUNC(l_codec_get_audio_info)},
  507. { "data", ROREG_FUNC(l_codec_get_audio_data)},
  508. { "encode", ROREG_FUNC(l_codec_encode_audio_data)},
  509. { "release", ROREG_FUNC(l_codec_release)},
  510. //@const MP3 number MP3格式
  511. { "MP3", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_MP3)},
  512. //@const WAV number WAV格式
  513. { "WAV", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_WAV)},
  514. //@const AMR number AMR-NB格式,一般意义上的AMR
  515. { "AMR", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB)},
  516. //@const AMR_WB number AMR-WB格式
  517. { "AMR_WB", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB)},
  518. { NULL, ROREG_INT(0)}
  519. };
  520. LUAMOD_API int luaopen_multimedia_codec( lua_State *L ) {
  521. luat_newlib2(L, reg_codec);
  522. luaL_newmetatable(L, LUAT_M_CODE_TYPE); /* create metatable for file handles */
  523. lua_pushcfunction(L, l_codec_gc);
  524. lua_setfield(L, -2, "__gc");
  525. lua_pop(L, 1); /* pop new metatable */
  526. return 1;
  527. }