luat_lib_multimedia_codec.c 20 KB

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