Guest User

Untitled

a guest
Jun 22nd, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.90 KB | None | 0 0
  1. /***************************************************************************
  2. * __________ __ ___.
  3. * Open \______ \ ____ ____ | | _\_ |__ _______ ___
  4. * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
  5. * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
  6. * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
  7. * \/ \/ \/ \/ \/
  8. * $Id:$
  9. *
  10. * Copyright (C) 2009 Mohamed Tarek
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version 2
  15. * of the License, or (at your option) any later version.
  16. *
  17. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  18. * KIND, either express or implied.
  19. *
  20. ****************************************************************************/
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include <inttypes.h>
  26.  
  27. #include <codecs/librm/rm.h>
  28. #include "system.h"
  29. #include "metadata.h"
  30. #include "metadata_common.h"
  31. #include "metadata_parsers.h"
  32. #include "logf.h"
  33.  
  34. //#define DEBUG_RM
  35. #define MAX_STRING 92 /* Size of id3v1 buffers in metadata.h */
  36. #ifndef DEBUG_RM
  37. #undef DEBUGF
  38. #define DEBUGF(...)
  39. #endif
  40.  
  41. static inline int read_cook_extradata(int fd, RMContext *rmctx) {
  42. read_uint32be(fd, &rmctx->cook_version);
  43. read_uint16be(fd, &rmctx->samples_pf_pc);
  44. read_uint16be(fd, &rmctx->nb_subbands);
  45. if(rmctx->extradata_size == 16) {
  46. lseek(fd, sizeof(uint32_t), SEEK_CUR); /* reserved */
  47. read_uint16be(fd, &rmctx->js_subband_start);
  48. read_uint16be(fd, &rmctx->js_vlc_bits);
  49. }
  50. return rmctx->extradata_size; /* for 'skipped' */
  51. }
  52.  
  53. static inline void print_cook_extradata(RMContext *rmctx) {
  54.  
  55. DEBUGF(" cook_version = 0x%08lx\n", rmctx->cook_version);
  56. DEBUGF(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc);
  57. DEBUGF(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands);
  58. if(rmctx->extradata_size == 16) {
  59. DEBUGF(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start);
  60. DEBUGF(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits);
  61. }
  62. }
  63.  
  64.  
  65. struct real_object_t
  66. {
  67. uint32_t fourcc;
  68. uint32_t size;
  69. uint16_t version;
  70. };
  71.  
  72. #define FOURCC(a,b,c,d) (((a)<<24) | ((b) << 16) | ((c) << 8) | (d))
  73.  
  74. static int real_read_object_header(int fd, struct real_object_t* obj)
  75. {
  76. int n;
  77.  
  78. if ((n = read_uint32be(fd, &obj->fourcc)) <= 0) return n;
  79. if ((n = read_uint32be(fd, &obj->size)) <= 0) return n;
  80. if ((n = read_uint16be(fd, &obj->version)) <= 0) return n;
  81.  
  82. return 1;
  83. }
  84.  
  85. static char* fourcc2str(uint32_t f)
  86. {
  87. static char res[5];
  88.  
  89. res[0] = (f & 0xff000000) >> 24;
  90. res[1] = (f & 0xff0000) >> 16;
  91. res[2] = (f & 0xff00) >> 8;
  92. res[3] = (f & 0xff);
  93. res[4] = 0;
  94.  
  95. return res;
  96. }
  97.  
  98. static int real_read_audio_stream_info(int fd, RMContext *rmctx)
  99. {
  100. int skipped = 0;
  101. uint32_t version;
  102. struct real_object_t obj;
  103. memset(&obj,0,sizeof(obj));
  104. uint32_t header_size;
  105. uint16_t flavor;
  106. uint32_t coded_framesize;
  107. uint8_t unknown8;
  108. uint16_t unknown16;
  109. uint32_t unknown32;
  110. uint8_t interleaver_id_length;
  111. uint32_t interleaver_id;
  112. uint8_t fourcc_length;
  113. uint32_t fourcc = 0;
  114.  
  115.  
  116. read_uint32be(fd, &version);
  117. skipped += 4;
  118.  
  119. DEBUGF(" version=0x%04lx\n",((version >> 16) & 0xff));
  120. if (((version >> 16) & 0xff) == 3) {
  121. /* Very old version */
  122. } else {
  123. real_read_object_header(fd, &obj);
  124. skipped += 10;
  125. read_uint32be(fd, &header_size);
  126. skipped += 4;
  127. /* obj.size will be filled with an unknown value, replaced with header_size */
  128. DEBUGF(" Object: %s, size: %ld bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version);
  129.  
  130. lseek(fd, 18, SEEK_CUR);
  131. read_uint16be(fd, &rmctx->sub_packet_h);
  132. read_uint16be(fd, &rmctx->block_align);
  133. read_uint16be(fd, &rmctx->sub_packet_size);
  134. read_uint16be(fd, &unknown16);
  135. skipped += 26;
  136. if (((version >> 16) & 0xff) == 5)
  137. {
  138. lseek(fd, 6, SEEK_CUR);
  139. skipped += 6;
  140. }
  141. read_uint16be(fd, &rmctx->sample_rate);
  142. read_uint32be(fd, &unknown32);
  143. read_uint16be(fd, &rmctx->nb_channels);
  144. skipped += 8;
  145. if (((version >> 16) & 0xff) == 4)
  146. {
  147. lseek(fd, 10, SEEK_CUR);
  148. skipped += 10;
  149. }
  150. if (((version >> 16) & 0xff) == 5)
  151. {
  152. lseek(fd, 8, SEEK_CUR);
  153. skipped += 8;
  154. }
  155. lseek(fd, 3, SEEK_CUR);
  156. skipped += 3;
  157. if (((version >> 16) & 0xff) == 5)
  158. {
  159. read_uint8(fd, &unknown8);
  160. skipped += 1;
  161. }
  162.  
  163. read_uint32be(fd, &rmctx->extradata_size);
  164. skipped += 4;
  165. if(!strncmp(fourcc2str(fourcc),"cook",4)){
  166. skipped += read_cook_extradata(fd, rmctx);
  167. rmctx->codec_type = cook;
  168. }
  169.  
  170.  
  171. DEBUGF(" flavor = %d\n",flavor);
  172. DEBUGF(" coded_frame_size = %ld\n",coded_framesize);
  173. DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h);
  174. DEBUGF(" frame_size = %d\n",rmctx->block_align);
  175. DEBUGF(" sub_packet_size = %d\n",rmctx->sub_packet_size);
  176. DEBUGF(" sample_rate= %d\n",rmctx->sample_rate);
  177. DEBUGF(" channels= %d\n",rmctx->nb_channels);
  178. DEBUGF(" fourcc = %s\n",fourcc2str(fourcc));
  179. DEBUGF(" codec_extra_data_length = %ld\n",rmctx->extradata_size);
  180. DEBUGF(" codec_extradata :\n");
  181. print_cook_extradata(rmctx);
  182.  
  183. }
  184.  
  185. return skipped;
  186. }
  187.  
  188. static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
  189. {
  190. struct real_object_t obj;
  191. memset(&obj,0,sizeof(obj));
  192. int res;
  193. int skipped;
  194. off_t curpos;
  195. uint8_t len; /* Holds a string_length, which is then passed to read_string() */
  196.  
  197. //uint32_t unknown32;
  198.  
  199. uint32_t max_bitrate;
  200. uint32_t avg_bitrate = 0;
  201. uint32_t max_packet_size;
  202. uint32_t avg_packet_size;
  203. uint32_t packet_count;
  204. uint32_t duration;
  205. uint32_t preroll;
  206. uint32_t index_offset;
  207. uint16_t num_streams;
  208.  
  209. uint16_t stream_id;
  210. uint32_t start_time;
  211. uint32_t codec_data_size;
  212. uint32_t v;
  213.  
  214. uint32_t next_data_off;
  215. uint8_t header_end;
  216.  
  217. curpos = lseek(fd, 0, SEEK_SET);
  218. res = real_read_object_header(fd, &obj);
  219.  
  220. if (obj.fourcc == FOURCC('.','r','a',0xfd))
  221. {
  222. /* Very old .ra format - not yet supported */
  223. return -1;
  224. }
  225. else if (obj.fourcc != FOURCC('.','R','M','F'))
  226. {
  227. return -1;
  228. }
  229.  
  230. /* Skip 2 dword unknowns */
  231. lseek(fd, 2*sizeof(uint32_t), SEEK_CUR);
  232.  
  233. DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
  234.  
  235. res = real_read_object_header(fd, &obj);
  236. header_end = 0;
  237. while(res)
  238. {
  239. DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
  240. skipped = 10;
  241. if(obj.fourcc == FOURCC('I','N','D','X'))
  242. break;
  243. switch (obj.fourcc)
  244. {
  245. case FOURCC('P','R','O','P'): /* File properties */
  246. read_uint32be(fd, &max_bitrate);
  247. read_uint32be(fd, &rmctx->bit_rate); /*avg bitrate*/
  248. lseek(fd, 12, SEEK_CUR);
  249. read_uint32be(fd, &rmctx->duration);
  250. lseek(fd, 8, SEEK_CUR);
  251. read_uint32be(fd, &rmctx->data_offset);
  252. read_uint16be(fd, &num_streams);
  253. read_uint16be(fd, &rmctx->flags);
  254. skipped += 40;
  255.  
  256. DEBUGF(" max_bitrate = %ld\n",max_bitrate);
  257. DEBUGF(" avg_bitrate = %ld\n",avg_bitrate);
  258. DEBUGF(" max_packet_size = %ld\n",max_packet_size);
  259. DEBUGF(" avg_packet_size = %ld\n",avg_packet_size);
  260. DEBUGF(" packet_count = %ld\n",packet_count);
  261. DEBUGF(" duration = %ld\n",rmctx->duration);
  262. DEBUGF(" preroll = %ld\n",preroll);
  263. DEBUGF(" index_offset = %ld\n",index_offset);
  264. DEBUGF(" data_offset = %ld\n",rmctx->data_offset);
  265. DEBUGF(" num_streams = %d\n",num_streams);
  266. DEBUGF(" flags=0x%04x\n",rmctx->flags);
  267. break;
  268.  
  269. case FOURCC('C','O','N','T'):
  270. /* Four strings - Title, Author, Copyright, Comment */
  271. read_uint8(fd,&len);
  272. skipped += (int)read_string(fd, id3->id3v1buf[0], MAX_STRING, '\0', len);
  273. read_uint8(fd,&len);
  274. skipped += (int)read_string(fd, id3->id3v1buf[1], MAX_STRING, '\0', len);
  275. read_uint8(fd,&len);
  276. skipped += (int)read_string(fd, id3->id3v1buf[2], MAX_STRING, '\0', len);
  277. read_uint8(fd,&len);
  278. skipped += (int)read_string(fd, id3->id3v1buf[3], MAX_STRING, '\0', len);
  279. skipped += 4;
  280.  
  281. DEBUGF(" title=\"%s\"\n",id3->id3v1buf[0]);
  282. DEBUGF(" author=\"%s\"\n",id3->id3v1buf[1]);
  283. DEBUGF(" copyright=\"%s\"\n",id3->id3v1buf[2]);
  284. DEBUGF(" comment=\"%s\"\n",id3->id3v1buf[3]);
  285. break;
  286.  
  287. case FOURCC('M','D','P','R'): /* Media properties */
  288. lseek(fd, 30, SEEK_CUR);
  289. skipped += 30;
  290. read_uint8(fd,&len);
  291. skipped += 1;
  292. lseek(fd, len, SEEK_CUR); /* desc */
  293. skipped += len;
  294. read_uint8(fd,&len);
  295. skipped += 1;
  296. lseek(fd, len + 4, SEEK_CUR); /* mimetype */
  297. skipped += len + 4;
  298. //From ffmpeg: codec_pos = url_ftell(pb);
  299. //read_uint32be(fd,&v);
  300.  
  301. DEBUGF(" stream_id = 0x%04x\n",stream_id);
  302. DEBUGF(" max_bitrate = %ld\n",max_bitrate);
  303. DEBUGF(" avg_bitrate = %ld\n",avg_bitrate);
  304. DEBUGF(" max_packet_size = %ld\n",max_packet_size);
  305. DEBUGF(" avg_packet_size = %ld\n",avg_packet_size);
  306. DEBUGF(" start_time = %ld\n",start_time);
  307. DEBUGF(" preroll = %ld\n",preroll);
  308. DEBUGF(" duration = %ld\n",duration);
  309. DEBUGF(" codec_data_size = %ld\n",codec_data_size);
  310. DEBUGF(" v=\"%s\"\n", fourcc2str(v));
  311.  
  312. if (v == FOURCC('.','r','a',0xfd))
  313. {
  314. skipped += real_read_audio_stream_info(fd, rmctx);
  315. }
  316.  
  317. break;
  318.  
  319. case FOURCC('D','A','T','A'):
  320. read_uint32be(fd,&rmctx->nb_packets);
  321. skipped += 4;
  322. read_uint32be(fd,&next_data_off);
  323. skipped += 4;
  324.  
  325. /***
  326. * nb_packets correction :
  327. * in some samples, number of packets may not exactly form
  328. * an integer number of scrambling units. This is corrected
  329. * by constructing a partially filled unit out of the few
  330. * remaining samples at the end of decoding.
  331. ***/
  332. if(rmctx->nb_packets % rmctx->sub_packet_h)
  333. rmctx->nb_packets += rmctx->sub_packet_h - (rmctx->nb_packets % rmctx->sub_packet_h);
  334.  
  335. DEBUGF(" data_nb_packets = %ld\n",rmctx->nb_packets);
  336. DEBUGF(" next DATA offset = %ld\n",next_data_off);
  337. header_end = 1;
  338. break;
  339. }
  340. if(header_end) break;
  341. curpos = lseek(fd, obj.size - skipped, SEEK_CUR);
  342. res = real_read_object_header(fd, &obj);
  343. }
  344.  
  345.  
  346. return 0;
  347. }
  348.  
  349. static void copy_metadata(struct mp3entry *id3, RMContext *rmctx)
  350. {
  351. /* Copy tags */
  352. id3->title = id3->id3v1buf[0];
  353. id3->artist = id3->id3v1buf[1];
  354. id3->comment = id3->id3v1buf[3];
  355.  
  356. /* Copy stream parameters */
  357. id3->bitrate = rmctx->bit_rate / 1000;
  358. id3->frequency = rmctx->sample_rate;
  359. id3->length = rmctx->duration;
  360. switch(rmctx->codec_type)
  361. {
  362. case cook:
  363. id3->codectype = AFMT_COOK;
  364. break;
  365. }
  366. memcpy(id3->id3v2buf, rmctx, sizeof(RMContext));
  367.  
  368. }
  369.  
  370. bool get_rm_metadata(int fd, struct mp3entry* id3)
  371. {
  372. RMContext rmctx;
  373. memset(&rmctx,0,sizeof(RMContext));
  374. rm_parse_header(fd, &rmctx, id3);
  375. copy_metadata(id3, &rmctx);
  376. id3->filesize = filesize(fd);
  377. return true;
  378. }
Add Comment
Please, Sign In to add comment