/src/dump_yaml.c

https://code.google.com/ · C · 429 lines · 296 code · 94 blank · 39 comment · 18 complexity · 8f79d36164538a9f2f7f63fd574133db MD5 · raw file

  1. /*
  2. $Id: dump_yaml.c 231 2011-06-27 13:46:19Z marc.noirot $
  3. FLV Metadata updater
  4. Copyright (C) 2007-2012 Marc Noirot <marc.noirot AT gmail.com>
  5. This file is part of FLVMeta.
  6. FLVMeta is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. FLVMeta is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with FLVMeta; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "dump.h"
  19. #include "dump_yaml.h"
  20. #include "yaml.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. /* YAML metadata dumping */
  24. static void amf_data_yaml_dump(const amf_data * data, yaml_emitter_t * emitter) {
  25. if (data != NULL) {
  26. amf_node * node;
  27. yaml_event_t event;
  28. time_t time;
  29. struct tm * t;
  30. char str[128];
  31. switch (data->type) {
  32. case AMF_TYPE_NUMBER:
  33. sprintf(str, "%.12g", data->number_data);
  34. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  35. yaml_emitter_emit(emitter, &event);
  36. break;
  37. case AMF_TYPE_BOOLEAN:
  38. sprintf(str, (data->boolean_data) ? "true" : "false");
  39. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  40. yaml_emitter_emit(emitter, &event);
  41. break;
  42. case AMF_TYPE_STRING:
  43. yaml_scalar_event_initialize(&event, NULL, NULL, amf_string_get_bytes(data), (int)amf_string_get_size(data), 1, 1, YAML_ANY_SCALAR_STYLE);
  44. yaml_emitter_emit(emitter, &event);
  45. break;
  46. case AMF_TYPE_OBJECT:
  47. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  48. yaml_emitter_emit(emitter, &event);
  49. node = amf_object_first(data);
  50. while (node != NULL) {
  51. amf_data * name;
  52. name = amf_object_get_name(node);
  53. /* if this fails, we skip the current entry */
  54. if (yaml_scalar_event_initialize(&event, NULL, NULL, amf_string_get_bytes(name), amf_string_get_size(name), 1, 1, YAML_ANY_SCALAR_STYLE)) {
  55. yaml_emitter_emit(emitter, &event);
  56. amf_data_yaml_dump(amf_object_get_data(node), emitter);
  57. }
  58. node = amf_object_next(node);
  59. }
  60. yaml_mapping_end_event_initialize(&event);
  61. yaml_emitter_emit(emitter, &event);
  62. break;
  63. case AMF_TYPE_NULL:
  64. case AMF_TYPE_UNDEFINED:
  65. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"null", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  66. yaml_emitter_emit(emitter, &event);
  67. break;
  68. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  69. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  70. yaml_emitter_emit(emitter, &event);
  71. node = amf_associative_array_first(data);
  72. while (node != NULL) {
  73. amf_data * name;
  74. name = amf_associative_array_get_name(node);
  75. /* if this fails, we skip the current entry */
  76. if (yaml_scalar_event_initialize(&event, NULL, NULL, amf_string_get_bytes(name), amf_string_get_size(name), 1, 1, YAML_ANY_SCALAR_STYLE)) {
  77. yaml_emitter_emit(emitter, &event);
  78. amf_data_yaml_dump(amf_associative_array_get_data(node), emitter);
  79. }
  80. node = amf_associative_array_next(node);
  81. }
  82. yaml_mapping_end_event_initialize(&event);
  83. yaml_emitter_emit(emitter, &event);
  84. break;
  85. case AMF_TYPE_ARRAY:
  86. yaml_sequence_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_SEQUENCE_STYLE);
  87. yaml_emitter_emit(emitter, &event);
  88. node = amf_array_first(data);
  89. while (node != NULL) {
  90. amf_data_yaml_dump(amf_array_get(node), emitter);
  91. node = amf_array_next(node);
  92. }
  93. yaml_sequence_end_event_initialize(&event);
  94. yaml_emitter_emit(emitter, &event);
  95. break;
  96. case AMF_TYPE_DATE:
  97. time = amf_date_to_time_t(data);
  98. tzset();
  99. t = localtime(&time);
  100. strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%S", t);
  101. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  102. yaml_emitter_emit(emitter, &event);
  103. break;
  104. case AMF_TYPE_XML: break;
  105. case AMF_TYPE_CLASS: break;
  106. default: break;
  107. }
  108. }
  109. }
  110. /* YAML FLV file full dump callbacks */
  111. static int yaml_on_header(flv_header * header, flv_parser * parser) {
  112. yaml_emitter_t * emitter;
  113. yaml_event_t event;
  114. char buffer[20];
  115. emitter = (yaml_emitter_t *)parser->user_data;
  116. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  117. yaml_emitter_emit(emitter, &event);
  118. /* magic */
  119. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"magic", 5, 1, 1, YAML_ANY_SCALAR_STYLE);
  120. yaml_emitter_emit(emitter, &event);
  121. sprintf(buffer, "%.3s", header->signature);
  122. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  123. yaml_emitter_emit(emitter, &event);
  124. /* hasVideo */
  125. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"hasVideo", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
  126. yaml_emitter_emit(emitter, &event);
  127. sprintf(buffer, "%s", flv_header_has_video(*header) ? "true" : "false");
  128. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  129. yaml_emitter_emit(emitter, &event);
  130. /* hasAudio */
  131. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"hasAudio", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
  132. yaml_emitter_emit(emitter, &event);
  133. sprintf(buffer, "%s", flv_header_has_audio(*header) ? "true" : "false");
  134. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  135. yaml_emitter_emit(emitter, &event);
  136. /* version */
  137. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"version", 7, 1, 1, YAML_ANY_SCALAR_STYLE);
  138. yaml_emitter_emit(emitter, &event);
  139. sprintf(buffer, "%i", header->version);
  140. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  141. yaml_emitter_emit(emitter, &event);
  142. /* start of tags array */
  143. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"tags", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  144. yaml_emitter_emit(emitter, &event);
  145. yaml_sequence_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_SEQUENCE_STYLE);
  146. yaml_emitter_emit(emitter, &event);
  147. return OK;
  148. }
  149. static int yaml_on_tag(flv_tag * tag, flv_parser * parser) {
  150. const char * str;
  151. yaml_emitter_t * emitter;
  152. yaml_event_t event;
  153. char buffer[20];
  154. emitter = (yaml_emitter_t *)parser->user_data;
  155. str = dump_string_get_tag_type(tag);
  156. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  157. yaml_emitter_emit(emitter, &event);
  158. /* type */
  159. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"type", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  160. yaml_emitter_emit(emitter, &event);
  161. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  162. yaml_emitter_emit(emitter, &event);
  163. /* timestamp */
  164. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"timestamp", 9, 1, 1, YAML_ANY_SCALAR_STYLE);
  165. yaml_emitter_emit(emitter, &event);
  166. sprintf(buffer, "%i", flv_tag_get_timestamp(*tag));
  167. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  168. yaml_emitter_emit(emitter, &event);
  169. /* data size */
  170. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"dataSize", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
  171. yaml_emitter_emit(emitter, &event);
  172. sprintf(buffer, "%i", flv_tag_get_body_length(*tag));
  173. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  174. yaml_emitter_emit(emitter, &event);
  175. /* offset */
  176. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"offset", 6, 1, 1, YAML_ANY_SCALAR_STYLE);
  177. yaml_emitter_emit(emitter, &event);
  178. sprintf(buffer, "%" FILE_OFFSET_PRINTF_FORMAT "i", parser->stream->current_tag_offset);
  179. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
  180. yaml_emitter_emit(emitter, &event);
  181. return OK;
  182. }
  183. static int yaml_on_video_tag(flv_tag * tag, flv_video_tag vt, flv_parser * parser) {
  184. const char * str;
  185. yaml_emitter_t * emitter;
  186. yaml_event_t event;
  187. emitter = (yaml_emitter_t *)parser->user_data;
  188. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"videoData", 9, 1, 1, YAML_ANY_SCALAR_STYLE);
  189. yaml_emitter_emit(emitter, &event);
  190. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  191. yaml_emitter_emit(emitter, &event);
  192. str = dump_string_get_video_codec(vt);
  193. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"codecID", 7, 1, 1, YAML_ANY_SCALAR_STYLE);
  194. yaml_emitter_emit(emitter, &event);
  195. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  196. yaml_emitter_emit(emitter, &event);
  197. str = dump_string_get_video_frame_type(vt);
  198. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"frameType", 9, 1, 1, YAML_ANY_SCALAR_STYLE);
  199. yaml_emitter_emit(emitter, &event);
  200. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  201. yaml_emitter_emit(emitter, &event);
  202. yaml_mapping_end_event_initialize(&event);
  203. yaml_emitter_emit(emitter, &event);
  204. return OK;
  205. }
  206. static int yaml_on_audio_tag(flv_tag * tag, flv_audio_tag at, flv_parser * parser) {
  207. const char * str;
  208. yaml_emitter_t * emitter;
  209. yaml_event_t event;
  210. emitter = (yaml_emitter_t *)parser->user_data;
  211. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"audioData", 9, 1, 1, YAML_ANY_SCALAR_STYLE);
  212. yaml_emitter_emit(emitter, &event);
  213. yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_ANY_MAPPING_STYLE);
  214. yaml_emitter_emit(emitter, &event);
  215. str = dump_string_get_sound_type(at);
  216. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"type", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  217. yaml_emitter_emit(emitter, &event);
  218. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  219. yaml_emitter_emit(emitter, &event);
  220. str = dump_string_get_sound_size(at);
  221. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"size", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  222. yaml_emitter_emit(emitter, &event);
  223. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  224. yaml_emitter_emit(emitter, &event);
  225. str = dump_string_get_sound_rate(at);
  226. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"rate", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
  227. yaml_emitter_emit(emitter, &event);
  228. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  229. yaml_emitter_emit(emitter, &event);
  230. str = dump_string_get_sound_format(at);
  231. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"format", 6, 1, 1, YAML_ANY_SCALAR_STYLE);
  232. yaml_emitter_emit(emitter, &event);
  233. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)str, (int)strlen(str), 1, 1, YAML_ANY_SCALAR_STYLE);
  234. yaml_emitter_emit(emitter, &event);
  235. yaml_mapping_end_event_initialize(&event);
  236. yaml_emitter_emit(emitter, &event);
  237. return OK;
  238. }
  239. static int yaml_on_metadata_tag(flv_tag * tag, amf_data * name, amf_data * data, flv_parser * parser) {
  240. yaml_emitter_t * emitter;
  241. yaml_event_t event;
  242. emitter = (yaml_emitter_t *)parser->user_data;
  243. yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"scriptDataObject", 16, 1, 1, YAML_ANY_SCALAR_STYLE);
  244. yaml_emitter_emit(emitter, &event);
  245. amf_data_yaml_dump(data, emitter);
  246. return OK;
  247. }
  248. static int yaml_on_prev_tag_size(uint32 size, flv_parser * parser) {
  249. yaml_emitter_t * emitter;
  250. yaml_event_t event;
  251. emitter = (yaml_emitter_t *)parser->user_data;
  252. yaml_mapping_end_event_initialize(&event);
  253. yaml_emitter_emit(emitter, &event);
  254. return OK;
  255. }
  256. static int yaml_on_stream_end(flv_parser * parser) {
  257. yaml_emitter_t * emitter;
  258. yaml_event_t event;
  259. emitter = (yaml_emitter_t *)parser->user_data;
  260. yaml_sequence_end_event_initialize(&event);
  261. yaml_emitter_emit(emitter, &event);
  262. yaml_mapping_end_event_initialize(&event);
  263. yaml_emitter_emit(emitter, &event);
  264. return OK;
  265. }
  266. /* YAML FLV file metadata dump callbacks */
  267. static int yaml_on_metadata_tag_only(flv_tag * tag, amf_data * name, amf_data * data, flv_parser * parser) {
  268. flvmeta_opts * options = (flvmeta_opts*) parser->user_data;
  269. if (options->metadata_event == NULL) {
  270. if (!strcmp((char*)amf_string_get_bytes(name), "onMetaData")) {
  271. dump_yaml_amf_data(data);
  272. return FLVMETA_DUMP_STOP_OK;
  273. }
  274. }
  275. else {
  276. if (!strcmp((char*)amf_string_get_bytes(name), options->metadata_event)) {
  277. dump_yaml_amf_data(data);
  278. }
  279. }
  280. return OK;
  281. }
  282. /* dumping functions */
  283. void dump_yaml_setup_metadata_dump(flv_parser * parser) {
  284. if (parser != NULL) {
  285. parser->on_metadata_tag = yaml_on_metadata_tag_only;
  286. }
  287. }
  288. int dump_yaml_file(flv_parser * parser, const flvmeta_opts * options) {
  289. yaml_emitter_t emitter;
  290. yaml_event_t event;
  291. int ret;
  292. parser->on_header = yaml_on_header;
  293. parser->on_tag = yaml_on_tag;
  294. parser->on_audio_tag = yaml_on_audio_tag;
  295. parser->on_video_tag = yaml_on_video_tag;
  296. parser->on_metadata_tag = yaml_on_metadata_tag;
  297. parser->on_prev_tag_size = yaml_on_prev_tag_size;
  298. parser->on_stream_end = yaml_on_stream_end;
  299. yaml_emitter_initialize(&emitter);
  300. yaml_emitter_set_output_file(&emitter, stdout);
  301. yaml_emitter_open(&emitter);
  302. yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
  303. yaml_emitter_emit(&emitter, &event);
  304. parser->user_data = &emitter;
  305. ret = flv_parse(options->input_file, parser);
  306. yaml_document_end_event_initialize(&event, 1);
  307. yaml_emitter_emit(&emitter, &event);
  308. yaml_emitter_flush(&emitter);
  309. yaml_emitter_close(&emitter);
  310. yaml_emitter_delete(&emitter);
  311. return ret;
  312. }
  313. int dump_yaml_amf_data(const amf_data * data) {
  314. yaml_emitter_t emitter;
  315. yaml_event_t event;
  316. yaml_emitter_initialize(&emitter);
  317. yaml_emitter_set_output_file(&emitter, stdout);
  318. yaml_emitter_open(&emitter);
  319. yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
  320. yaml_emitter_emit(&emitter, &event);
  321. /* dump AMF into YAML */
  322. amf_data_yaml_dump(data, &emitter);
  323. yaml_document_end_event_initialize(&event, 1);
  324. yaml_emitter_emit(&emitter, &event);
  325. yaml_emitter_flush(&emitter);
  326. yaml_emitter_close(&emitter);
  327. yaml_emitter_delete(&emitter);
  328. return OK;
  329. }