luat_lib_multimedia_codec.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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. #include "dec_if.h"
  21. static const uint8_t amr_nb_byte_len[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
  22. static const uint8_t amr_wb_byte_len[16] = {17, 23, 32, 36, 40, 46, 50, 58, 60, 5,0, 0, 0, 0, 0, 0};
  23. typedef void (*amr_decode_fun_t)(void* state, const unsigned char* in, short* out, int bfi);
  24. #endif
  25. #ifdef LUAT_USE_AUDIO_G711
  26. #include "g711_codec/g711_codec.h"
  27. #endif
  28. #ifndef G711_PCM_SAMPLES
  29. #define G711_PCM_SAMPLES 160
  30. #endif
  31. #ifndef MINIMP3_MAX_SAMPLES_PER_FRAME
  32. #define MINIMP3_MAX_SAMPLES_PER_FRAME (2*1152)
  33. #endif
  34. /**
  35. 创建编解码用的codec
  36. @api codec.create(type, isDecoder, quality)
  37. @int 多媒体类型,目前支持codec.MP3 codec.AMR
  38. @boolean 是否是解码器,true解码器,false编码器,默认true,是解码器
  39. @int 编码等级,部分bsp有内部编解码器,可能需要提前输入编解码等级,不知道的就填7
  40. @return userdata 成功返回一个数据结构,否则返回nil
  41. @usage
  42. -- 目前支持:
  43. -- codec.MP3 解码
  44. -- codec.AMR 编码+解码
  45. -- codec.AMR_WB 编码(部分BSP支持,例如Air780EHM,Air8000)+解码
  46. -- codec.WAV WAV本身就是PCM数据,无需编解码
  47. -- codec.ULAW codec.ALAW 编码+解码
  48. -- 创建解码器
  49. local decoder = codec.create(codec.MP3)--创建一个mp3的decoder
  50. -- 创建编码器
  51. local encoder = codec.create(codec.AMR, false)--创建一个amr的encoder
  52. -- 创建编码器
  53. local encoder = codec.create(codec.AMR_WB, false, 8)--创建一个amr-wb的encoder,编码等级默认8
  54. */
  55. static int l_codec_create(lua_State *L) {
  56. uint8_t type = luaL_optinteger(L, 1, LUAT_MULTIMEDIA_DATA_TYPE_MP3);
  57. uint8_t is_decoder = 1;
  58. if (lua_isboolean(L, 2)) {
  59. is_decoder = lua_toboolean(L, 2);
  60. }
  61. #ifdef LUAT_SUPPORT_AMR
  62. #ifdef LUAT_USE_INTER_AMR
  63. uint8_t encode_level = 7;
  64. switch (type) {
  65. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  66. encode_level = luaL_optinteger(L, 3, 7);
  67. break;
  68. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  69. encode_level = luaL_optinteger(L, 3, 8);
  70. break;
  71. default:
  72. break;
  73. }
  74. #endif
  75. #endif
  76. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)lua_newuserdata(L, sizeof(luat_multimedia_codec_t));
  77. if (coder == NULL) {
  78. lua_pushnil(L);
  79. } else {
  80. memset(coder, 0, sizeof(luat_multimedia_codec_t));
  81. coder->type = type;
  82. coder->is_decoder = is_decoder;
  83. if (is_decoder)
  84. {
  85. switch (type) {
  86. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  87. coder->mp3_decoder = mp3_decoder_create();
  88. if (!coder->mp3_decoder) {
  89. lua_pushnil(L);
  90. return 1;
  91. }
  92. break;
  93. #ifdef LUAT_SUPPORT_AMR
  94. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  95. coder->amr_coder = Decoder_Interface_init();
  96. if (!coder->amr_coder) {
  97. lua_pushnil(L);
  98. return 1;
  99. }
  100. break;
  101. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  102. coder->amr_coder = D_IF_init();
  103. if (!coder->amr_coder) {
  104. lua_pushnil(L);
  105. return 1;
  106. }
  107. break;
  108. #endif
  109. #ifdef LUAT_USE_AUDIO_G711
  110. case LUAT_MULTIMEDIA_DATA_TYPE_ULAW:
  111. case LUAT_MULTIMEDIA_DATA_TYPE_ALAW:
  112. // 使用专门的g711_codec字段存储G711解码器
  113. coder->g711_codec = g711_decoder_create(type);
  114. if (!coder->g711_codec) {
  115. lua_pushnil(L);
  116. return 1;
  117. }
  118. break;
  119. #endif
  120. }
  121. }
  122. else
  123. {
  124. switch (type) {
  125. #ifdef LUAT_SUPPORT_AMR
  126. #ifdef LUAT_USE_INTER_AMR
  127. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  128. coder->amr_coder = luat_audio_inter_amr_coder_init(0, encode_level);
  129. if (!coder->amr_coder) {
  130. lua_pushnil(L);
  131. return 1;
  132. }
  133. break;
  134. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  135. coder->amr_coder = luat_audio_inter_amr_coder_init(1, encode_level);
  136. if (!coder->amr_coder) {
  137. lua_pushnil(L);
  138. return 1;
  139. }
  140. break;
  141. #else
  142. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  143. coder->amr_coder = Encoder_Interface_init(0);
  144. if (!coder->amr_coder) {
  145. lua_pushnil(L);
  146. return 1;
  147. }
  148. break;
  149. #endif
  150. #endif
  151. #ifdef LUAT_USE_AUDIO_G711
  152. case LUAT_MULTIMEDIA_DATA_TYPE_ULAW:
  153. case LUAT_MULTIMEDIA_DATA_TYPE_ALAW:
  154. // 使用专门的g711_codec字段存储G711编码器
  155. coder->g711_codec = g711_encoder_create(type);
  156. if (!coder->g711_codec) {
  157. lua_pushnil(L);
  158. return 1;
  159. }
  160. break;
  161. #endif
  162. default:
  163. lua_pushnil(L);
  164. return 1;
  165. }
  166. }
  167. luaL_setmetatable(L, LUAT_M_CODE_TYPE);
  168. }
  169. return 1;
  170. }
  171. /**
  172. decoder从文件中解析出音频信息
  173. @api codec.info(decoder, file_path)
  174. @userdata 解码用的decoder
  175. @string 文件路径
  176. @return boolean 是否成功解析
  177. @return int 音频格式
  178. @return int 声音通道数
  179. @return int 采样频率
  180. @return int 采样位数
  181. @return boolean 是否有符号
  182. @usage
  183. local result, audio_format, num_channels, sample_rate, bits_per_sample, is_signed= codec.info(coder, "xxx")
  184. */
  185. static int l_codec_get_audio_info(lua_State *L) {
  186. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  187. uint32_t jump, i;
  188. uint8_t temp[16];
  189. int result = 0;
  190. int audio_format = LUAT_MULTIMEDIA_DATA_TYPE_NONE;
  191. uint8_t num_channels;
  192. uint32_t sample_rate;
  193. int bits_per_sample = 16;
  194. uint32_t align;
  195. int is_signed = 1;
  196. size_t len;
  197. const char *file_path = luaL_checklstring(L, 2, &len);
  198. FILE *fd = luat_fs_fopen(file_path, "r");
  199. if (fd && coder)
  200. {
  201. switch(coder->type)
  202. {
  203. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  204. mp3_decoder_init(coder->mp3_decoder);
  205. coder->buff.addr = luat_heap_malloc(MP3_FRAME_LEN);
  206. coder->buff.len = MP3_FRAME_LEN;
  207. coder->buff.used = luat_fs_fread(temp, 10, 1, fd);
  208. if (coder->buff.used != 10)
  209. {
  210. break;
  211. }
  212. if (!memcmp(temp, "ID3", 3))
  213. {
  214. jump = 0;
  215. for(i = 0; i < 4; i++)
  216. {
  217. jump <<= 7;
  218. jump |= temp[6 + i] & 0x7f;
  219. }
  220. // LLOGD("jump head %d", jump);
  221. luat_fs_fseek(fd, jump, SEEK_SET);
  222. }
  223. coder->buff.used = luat_fs_fread(coder->buff.addr, MP3_FRAME_LEN, 1, fd);
  224. result = mp3_decoder_get_info(coder->mp3_decoder, coder->buff.addr, coder->buff.used, &sample_rate, &num_channels);
  225. mp3_decoder_init(coder->mp3_decoder);
  226. audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
  227. break;
  228. case LUAT_MULTIMEDIA_DATA_TYPE_WAV:
  229. luat_fs_fread(temp, 12, 1, fd);
  230. if (!memcmp(temp, "RIFF", 4) || !memcmp(temp + 8, "WAVE", 4))
  231. {
  232. luat_fs_fread(temp, 8, 1, fd);
  233. if (!memcmp(temp, "fmt ", 4))
  234. {
  235. memcpy(&len, temp + 4, 4);
  236. coder->buff.addr = luat_heap_malloc(len);
  237. luat_fs_fread(coder->buff.addr, len, 1, fd);
  238. audio_format = coder->buff.addr[0];
  239. num_channels = coder->buff.addr[2];
  240. memcpy(&sample_rate, coder->buff.addr + 4, 4);
  241. align = coder->buff.addr[12];
  242. bits_per_sample = coder->buff.addr[14];
  243. coder->read_len = (align * sample_rate >> 3) & ~(3);
  244. // LLOGD("size %d", coder->read_len);
  245. luat_heap_free(coder->buff.addr);
  246. coder->buff.addr = NULL;
  247. luat_fs_fread(temp, 8, 1, fd);
  248. if (!memcmp(temp, "fact", 4))
  249. {
  250. memcpy(&len, temp + 4, 4);
  251. luat_fs_fseek(fd, len, SEEK_CUR);
  252. luat_fs_fread(temp, 8, 1, fd);
  253. }
  254. if (!memcmp(temp, "data", 4))
  255. {
  256. result = 1;
  257. }
  258. else
  259. {
  260. LLOGD("no data");
  261. result = 0;
  262. }
  263. }
  264. else
  265. {
  266. LLOGD("no fmt");
  267. }
  268. }
  269. else
  270. {
  271. LLOGD("head error");
  272. }
  273. break;
  274. #ifdef LUAT_SUPPORT_AMR
  275. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  276. luat_fs_fread(temp, 6, 1, fd);
  277. if (!memcmp(temp, "#!AMR\n", 6))
  278. {
  279. coder->buff.addr = luat_heap_malloc(320);
  280. if (coder->buff.addr)
  281. {
  282. num_channels = 1;
  283. sample_rate = 8000;
  284. audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
  285. result = 1;
  286. }
  287. }
  288. else
  289. {
  290. result = 0;
  291. }
  292. break;
  293. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  294. luat_fs_fread(temp, 9, 1, fd);
  295. if (!memcmp(temp, "#!AMR-WB\n", 9))
  296. {
  297. coder->buff.addr = luat_heap_malloc(640);
  298. if (coder->buff.addr)
  299. {
  300. num_channels = 1;
  301. sample_rate = 16000;
  302. audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
  303. result = 1;
  304. }
  305. }
  306. else
  307. {
  308. result = 0;
  309. }
  310. break;
  311. #endif
  312. #ifdef LUAT_USE_AUDIO_G711
  313. case LUAT_MULTIMEDIA_DATA_TYPE_ULAW:
  314. case LUAT_MULTIMEDIA_DATA_TYPE_ALAW:
  315. // G711固定参数:8kHz采样率, 单声道, 8位深度
  316. sample_rate = 8000;
  317. num_channels = 1;
  318. bits_per_sample = 8;
  319. audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
  320. result = 1;
  321. break;
  322. #endif
  323. default:
  324. break;
  325. }
  326. }
  327. if (!result)
  328. {
  329. luat_fs_fclose(fd);
  330. }
  331. else
  332. {
  333. coder->fd = fd;
  334. }
  335. lua_pushboolean(L, result);
  336. lua_pushinteger(L, audio_format);
  337. lua_pushinteger(L, num_channels);
  338. lua_pushinteger(L, sample_rate);
  339. lua_pushinteger(L, bits_per_sample);
  340. lua_pushboolean(L, is_signed);
  341. return 6;
  342. }
  343. /**
  344. decoder从文件中解析出原始音频数据,比如从MP3文件里解析出PCM数据,这里的文件路径已经在codec.info传入,不需要再次传入
  345. @api codec.data(decoder, out_buff, size)
  346. @userdata 解码用的decoder
  347. @zbuff 存放输出数据的zbuff,空间必须不少于16KB
  348. @int 最少解码出多少字节的音频数据,默认16384
  349. @return boolean 是否成功解析
  350. @usage
  351. -- 大内存设备
  352. local buff = zbuff.create(16*1024)
  353. local result = codec.data(coder, buff, 8192)
  354. -- 小内存设备
  355. local buff = zbuff.create(8*1024)
  356. local result = codec.data(coder, buff, 4096)
  357. */
  358. static int l_codec_get_audio_data(lua_State *L) {
  359. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  360. #ifdef LUAT_SUPPORT_AMR
  361. amr_decode_fun_t decode_if;
  362. uint32_t frame_len;
  363. uint8_t *size_table;
  364. uint8_t size;
  365. uint8_t temp[64];
  366. #endif
  367. uint32_t pos = 0;
  368. int read_len;
  369. int result = 0;
  370. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  371. uint32_t is_not_end = 1;
  372. uint32_t hz, out_len, used;
  373. size_t mini_output = luaL_optinteger(L, 3, 16384);
  374. if (mini_output > 16384)
  375. mini_output = 16384;
  376. else if (mini_output < 4 * 1024)
  377. mini_output = 4 * 1024;
  378. out_buff->used = 0;
  379. if (coder)
  380. {
  381. switch(coder->type)
  382. {
  383. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  384. GET_MP3_DATA:
  385. if (coder->buff.used < MINIMP3_MAX_SAMPLES_PER_FRAME)
  386. {
  387. read_len = luat_fs_fread((void*)(coder->buff.addr + coder->buff.used), MINIMP3_MAX_SAMPLES_PER_FRAME, 1, coder->fd);
  388. if (read_len > 0)
  389. {
  390. coder->buff.used += read_len;
  391. }
  392. else
  393. {
  394. is_not_end = 0;
  395. }
  396. }
  397. do
  398. {
  399. 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);
  400. if (result > 0)
  401. {
  402. out_buff->used += out_len;
  403. }
  404. if (result < 0) {
  405. return 0;
  406. }
  407. // if (!result) {
  408. // LLOGD("jump %dbyte", info.frame_bytes);
  409. // }
  410. pos += used;
  411. if ((out_buff->len - out_buff->used) < (MINIMP3_MAX_SAMPLES_PER_FRAME * 2))
  412. {
  413. break;
  414. }
  415. } while ((coder->buff.used - pos) >= (MINIMP3_MAX_SAMPLES_PER_FRAME * is_not_end + 1));
  416. // LLOGD("result %u,%u,%u,%u,%u", result, out_buff->used, coder->buff.used, pos, info.frame_bytes);
  417. if (pos >= coder->buff.used)
  418. {
  419. coder->buff.used = 0;
  420. }
  421. else
  422. {
  423. memmove(coder->buff.addr, coder->buff.addr + pos, coder->buff.used - pos);
  424. coder->buff.used -= pos;
  425. }
  426. pos = 0;
  427. if (!out_buff->used)
  428. {
  429. if (is_not_end)
  430. {
  431. goto GET_MP3_DATA;
  432. }
  433. else
  434. {
  435. result = 0;
  436. }
  437. }
  438. else
  439. {
  440. if ((out_buff->used < mini_output) && is_not_end)
  441. {
  442. goto GET_MP3_DATA;
  443. }
  444. result = 1;
  445. }
  446. break;
  447. case LUAT_MULTIMEDIA_DATA_TYPE_WAV:
  448. read_len = luat_fs_fread(out_buff->addr + out_buff->used, coder->read_len, 1, coder->fd);
  449. if (read_len > 0)
  450. {
  451. out_buff->used += read_len;
  452. result = 1;
  453. }
  454. else
  455. {
  456. result = 0;
  457. }
  458. break;
  459. #ifdef LUAT_SUPPORT_AMR
  460. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  461. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  462. if (coder->type == LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB)
  463. {
  464. frame_len = 320;
  465. size_table = amr_nb_byte_len;
  466. decode_if = Decoder_Interface_Decode;
  467. }
  468. else
  469. {
  470. frame_len = 640;
  471. size_table = amr_wb_byte_len;
  472. decode_if = D_IF_decode;
  473. }
  474. while ((out_buff->used < mini_output) && is_not_end && ((out_buff->len - out_buff->used) >= frame_len))
  475. {
  476. read_len = luat_fs_fread(temp, 1, 1, coder->fd);
  477. if (read_len <= 0)
  478. {
  479. is_not_end = 0;
  480. break;
  481. }
  482. size = size_table[(temp[0] >> 3) & 0x0f];
  483. if (size > 0)
  484. {
  485. read_len = luat_fs_fread(temp + 1, 1, size, coder->fd);
  486. if (read_len <= 0)
  487. {
  488. is_not_end = 0;
  489. break;
  490. }
  491. }
  492. decode_if(coder->amr_coder, temp, coder->buff.addr, 0);
  493. memcpy(out_buff->addr + out_buff->used, coder->buff.addr, frame_len);
  494. out_buff->used += frame_len;
  495. }
  496. result = 1;
  497. break;
  498. #endif
  499. #ifdef LUAT_USE_AUDIO_G711
  500. case LUAT_MULTIMEDIA_DATA_TYPE_ULAW:
  501. case LUAT_MULTIMEDIA_DATA_TYPE_ALAW:
  502. // 动态分配缓冲区
  503. if (!coder->buff.addr) {
  504. coder->buff.addr = luat_heap_malloc(G711_PCM_SAMPLES); // G711每帧160字节
  505. coder->buff.len = G711_PCM_SAMPLES;
  506. coder->buff.used = 0;
  507. }
  508. // 读取G711数据
  509. if (coder->buff.used < G711_PCM_SAMPLES) {
  510. read_len = luat_fs_fread((void*)(coder->buff.addr + coder->buff.used),
  511. G711_PCM_SAMPLES, 1, coder->fd);
  512. if (read_len > 0) {
  513. coder->buff.used += read_len;
  514. } else {
  515. is_not_end = 0;
  516. }
  517. }
  518. // 解码G711数据为PCM
  519. if (coder->buff.used >= G711_PCM_SAMPLES) {
  520. result = g711_decoder_get_data(coder->g711_codec, coder->buff.addr,
  521. coder->buff.used, (int16_t*)out_buff->addr + out_buff->used,
  522. &out_len, &used);
  523. if (result > 0) {
  524. out_buff->used += out_len;
  525. }
  526. // 移动缓冲区数据
  527. memmove(coder->buff.addr, coder->buff.addr + used, coder->buff.used - used);
  528. coder->buff.used -= used;
  529. }
  530. break;
  531. #endif
  532. default:
  533. break;
  534. }
  535. }
  536. lua_pushboolean(L, result);
  537. return 1;
  538. }
  539. /**
  540. 编码音频数据,由于flash和ram空间一般比较有限,除了部分bsp有内部amr编码功能以外只支持amr-nb编码
  541. @api codec.encode(coder, in_buffer, out_buffer, mode)
  542. @userdata codec.create创建的编解码用的coder
  543. @zbuff 输入的数据,zbuff形式,从0到used
  544. @zbuff 输出的数据,zbuff形式,自动添加到buff的尾部,如果空间大小不足,会自动扩展,但是会额外消耗时间,甚至会失败,所以尽量一开始就给足空间
  545. @int amr_nb的编码等级 0~7(即 MR475~MR122)值越大消耗的空间越多,音质越高,默认0 amr_wb的编码等级 0~8,值越大消耗的空间越多,音质越高,默认0
  546. @return boolean 成功返回true,失败返回false
  547. @usage
  548. codec.encode(amr_coder, inbuf, outbuf, codec.AMR_)
  549. */
  550. static int l_codec_encode_audio_data(lua_State *L) {
  551. #ifdef LUAT_SUPPORT_AMR
  552. #ifdef LUAT_USE_INTER_AMR
  553. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  554. luat_zbuff_t *in_buff;
  555. if (luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)){
  556. in_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  557. }else{
  558. in_buff = ((luat_zbuff_t *)lua_touserdata(L, 2));
  559. }
  560. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  561. if (!coder || !in_buff || !out_buff || (coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB && coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB && coder->type != LUAT_MULTIMEDIA_DATA_TYPE_ULAW && coder->type != LUAT_MULTIMEDIA_DATA_TYPE_ALAW) || coder->is_decoder)
  562. {
  563. lua_pushboolean(L, 0);
  564. return 1;
  565. }
  566. #ifdef LUAT_USE_AUDIO_G711
  567. if (coder->type == LUAT_MULTIMEDIA_DATA_TYPE_ULAW || coder->type == LUAT_MULTIMEDIA_DATA_TYPE_ALAW) {
  568. // G711编码处理 - 使用栈上分配的临时缓冲区,避免长期占用堆内存
  569. uint8_t outbuf[G711_PCM_SAMPLES]; // 栈上分配,用完即释放
  570. int16_t *pcm = (int16_t *)in_buff->addr;
  571. uint32_t total_len = in_buff->used >> 1; // 16位PCM转字节数
  572. uint32_t done_len = 0;
  573. uint32_t frame_size = G711_PCM_SAMPLES; // G711每帧160个PCM样本
  574. uint32_t out_len;
  575. // 处理完整的160样本帧
  576. while ((total_len - done_len) >= frame_size) {
  577. // 编码一帧PCM数据为G711
  578. int result = g711_encoder_get_data(coder->g711_codec, &pcm[done_len], frame_size,
  579. outbuf, &out_len);
  580. if (result > 0 && out_len > 0) {
  581. // 检查输出缓冲区空间
  582. if ((out_buff->len - out_buff->used) < out_len) {
  583. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len)) {
  584. lua_pushboolean(L, 0);
  585. return 1;
  586. }
  587. }
  588. // 复制编码后的数据到输出缓冲区
  589. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  590. out_buff->used += out_len;
  591. } else {
  592. }
  593. done_len += frame_size;
  594. }
  595. // 处理剩余的PCM样本(不足160个样本的部分)
  596. uint32_t remaining_len = total_len - done_len;
  597. if (remaining_len > 0) {
  598. // 用零填充到160个样本
  599. int16_t padded_frame[G711_PCM_SAMPLES] = {0};
  600. memcpy(padded_frame, &pcm[done_len], remaining_len * sizeof(int16_t));
  601. int result = g711_encoder_get_data(coder->g711_codec, padded_frame, frame_size,
  602. outbuf, &out_len);
  603. if (result > 0 && out_len > 0) {
  604. // 检查输出缓冲区空间
  605. if ((out_buff->len - out_buff->used) < out_len) {
  606. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len)) {
  607. lua_pushboolean(L, 0);
  608. return 1;
  609. }
  610. }
  611. // 复制编码后的数据到输出缓冲区
  612. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  613. out_buff->used += out_len;
  614. }
  615. }
  616. lua_pushboolean(L, 1);
  617. return 1;
  618. }
  619. #endif
  620. // AMR编码处理
  621. uint8_t outbuf[128];
  622. int16_t *pcm = (int16_t *)in_buff->addr;
  623. uint32_t total_len = in_buff->used >> 1;
  624. uint32_t done_len = 0;
  625. uint32_t pcm_len = (coder->type - LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB + 1) * 160;
  626. uint8_t out_len;
  627. while ((total_len - done_len) >= pcm_len)
  628. {
  629. luat_audio_inter_amr_coder_encode(coder->amr_coder, &pcm[done_len], outbuf, &out_len);
  630. if (out_len <= 0)
  631. {
  632. LLOGE("encode error in %d,result %d", done_len, out_len);
  633. }
  634. else
  635. {
  636. if ((out_buff->len - out_buff->used) < out_len)
  637. {
  638. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len))
  639. {
  640. lua_pushboolean(L, 0);
  641. return 1;
  642. }
  643. }
  644. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  645. out_buff->used += out_len;
  646. }
  647. done_len += pcm_len;
  648. }
  649. lua_pushboolean(L, 1);
  650. return 1;
  651. #else
  652. luat_multimedia_codec_t *coder = (luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE);
  653. luat_zbuff_t *in_buff;
  654. if (luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)){
  655. in_buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  656. }else{
  657. in_buff = ((luat_zbuff_t *)lua_touserdata(L, 2));
  658. }
  659. luat_zbuff_t *out_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  660. int mode = luaL_optinteger(L, 4, MR475);
  661. if (!coder || !in_buff || !out_buff || (coder->type != LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB) || coder->is_decoder)
  662. {
  663. lua_pushboolean(L, 0);
  664. return 1;
  665. }
  666. if (mode > MR122)
  667. {
  668. mode = MR475;
  669. }
  670. uint8_t outbuf[64];
  671. int16_t *pcm = (int16_t *)in_buff->addr;
  672. uint32_t total_len = in_buff->used >> 1;
  673. uint32_t done_len = 0;
  674. int out_len;
  675. while ((total_len - done_len) >= 160)
  676. {
  677. out_len = Encoder_Interface_Encode(coder->amr_coder, mode, &pcm[done_len], outbuf, 0);
  678. if (out_len <= 0)
  679. {
  680. LLOGE("encode error in %d,result %d", done_len, out_len);
  681. }
  682. else
  683. {
  684. if ((out_buff->len - out_buff->used) < out_len)
  685. {
  686. if (__zbuff_resize(out_buff, out_buff->len * 2 + out_len))
  687. {
  688. lua_pushboolean(L, 0);
  689. return 1;
  690. }
  691. }
  692. memcpy(out_buff->addr + out_buff->used, outbuf, out_len);
  693. out_buff->used += out_len;
  694. }
  695. done_len += 160;
  696. }
  697. lua_pushboolean(L, 1);
  698. return 1;
  699. #endif
  700. #else
  701. lua_pushboolean(L, 0);
  702. return 1;
  703. #endif
  704. }
  705. static int l_codec_gc(lua_State *L)
  706. {
  707. luat_multimedia_codec_t *coder = ((luat_multimedia_codec_t *)luaL_checkudata(L, 1, LUAT_M_CODE_TYPE));
  708. if (coder->fd) {
  709. luat_fs_fclose(coder->fd);
  710. coder->fd = NULL;
  711. }
  712. if (coder->buff.addr)
  713. {
  714. luat_heap_free(coder->buff.addr);
  715. coder->buff.addr = NULL;
  716. memset(&coder->buff, 0, sizeof(luat_zbuff_t));
  717. }
  718. switch(coder->type) {
  719. case LUAT_MULTIMEDIA_DATA_TYPE_MP3:
  720. if (coder->is_decoder && coder->mp3_decoder) {
  721. luat_heap_free(coder->mp3_decoder);
  722. coder->mp3_decoder = NULL;
  723. }
  724. break;
  725. #ifdef LUAT_SUPPORT_AMR
  726. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB:
  727. if (coder->amr_coder)
  728. {
  729. if (!coder->is_decoder)
  730. {
  731. #ifdef LUAT_USE_INTER_AMR
  732. luat_audio_inter_amr_coder_deinit(coder->amr_coder);
  733. #else
  734. Encoder_Interface_exit(coder->amr_coder);
  735. #endif
  736. }
  737. else
  738. {
  739. Decoder_Interface_exit(coder->amr_coder);
  740. }
  741. coder->amr_coder = NULL;
  742. }
  743. break;
  744. case LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB:
  745. if (coder->amr_coder)
  746. {
  747. if (!coder->is_decoder)
  748. {
  749. #ifdef LUAT_USE_INTER_AMR
  750. luat_audio_inter_amr_coder_deinit(coder->amr_coder);
  751. #else
  752. #endif
  753. }
  754. else
  755. {
  756. D_IF_exit(coder->amr_coder);
  757. }
  758. coder->amr_coder = NULL;
  759. }
  760. break;
  761. #endif
  762. #ifdef LUAT_USE_AUDIO_G711
  763. case LUAT_MULTIMEDIA_DATA_TYPE_ULAW:
  764. case LUAT_MULTIMEDIA_DATA_TYPE_ALAW:
  765. if (coder->g711_codec) {
  766. if (coder->is_decoder) {
  767. // 清理G711解码器
  768. g711_decoder_destroy(coder->g711_codec);
  769. } else {
  770. // 清理G711编码器
  771. g711_encoder_destroy(coder->g711_codec);
  772. }
  773. coder->g711_codec = NULL;
  774. }
  775. break;
  776. #endif
  777. }
  778. return 0;
  779. }
  780. /**
  781. 释放编解码用的coder
  782. @api codec.release(coder)
  783. @coder codec.create创建的编解码用的coder
  784. @usage
  785. codec.release(coder)
  786. */
  787. static int l_codec_release(lua_State *L) {
  788. return l_codec_gc(L);
  789. }
  790. static const rotable_Reg_t reg_codec[] =
  791. {
  792. { "create" , ROREG_FUNC(l_codec_create)},
  793. { "info" , ROREG_FUNC(l_codec_get_audio_info)},
  794. { "data", ROREG_FUNC(l_codec_get_audio_data)},
  795. { "encode", ROREG_FUNC(l_codec_encode_audio_data)},
  796. { "release", ROREG_FUNC(l_codec_release)},
  797. //@const MP3 number MP3格式
  798. { "MP3", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_MP3)},
  799. //@const WAV number WAV格式
  800. { "WAV", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_WAV)},
  801. //@const AMR number AMR-NB格式,一般意义上的AMR
  802. { "AMR", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB)},
  803. //@const AMR_WB number AMR-WB格式
  804. { "AMR_WB", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB)},
  805. //@const VDDA_3V3 number codec 电压: 3.3V
  806. { "VDDA_3V3", ROREG_INT(LUAT_CODEC_VDDA_3V3)},
  807. //@const VDDA_1V8 number codec 电压: 1.8V
  808. { "VDDA_1V8", ROREG_INT(LUAT_CODEC_VDDA_1V8)},
  809. //@const ULAW number G711 μ-law格式
  810. { "ULAW", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_ULAW)},
  811. //@const ALAW number G711 A-law格式
  812. { "ALAW", ROREG_INT(LUAT_MULTIMEDIA_DATA_TYPE_ALAW)},
  813. { NULL, ROREG_INT(0)}
  814. };
  815. LUAMOD_API int luaopen_multimedia_codec( lua_State *L ) {
  816. luat_newlib2(L, reg_codec);
  817. luaL_newmetatable(L, LUAT_M_CODE_TYPE); /* create metatable for file handles */
  818. lua_pushcfunction(L, l_codec_gc);
  819. lua_setfield(L, -2, "__gc");
  820. lua_pop(L, 1); /* pop new metatable */
  821. return 1;
  822. }