0003-parse-add-MPEG-4.patch 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. From f6a8b85db4d85d8e6101d1a73c825c7e6df52f3a Mon Sep 17 00:00:00 2001
  2. From: Marco Ballesio <marco.ballesio@nokia.com>
  3. Date: Fri, 5 Jun 2009 15:35:06 +0300
  4. Subject: [PATCH] parse: add MPEG-4
  5. Signed-off-by: Felipe Contreras <felipe.contreras@nokia.com>
  6. ---
  7. gstdspparse.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
  8. gstdspparse.h | 1 +
  9. gstdspvdec.c | 4 +-
  10. 3 files changed, 245 insertions(+), 2 deletions(-)
  11. diff --git a/gstdspparse.c b/gstdspparse.c
  12. index 299e86b..15c55a1 100644
  13. --- a/gstdspparse.c
  14. +++ b/gstdspparse.c
  15. @@ -3,7 +3,8 @@
  16. * Copyright (C) 2007-2009 Nokia Corporation
  17. *
  18. * Authors:
  19. - * Marco Ballesio <marco.ballesio@gmail.com>
  20. + * Juha Alanen <juha.m.alanen@nokia.com>
  21. + * Marco Ballesio <marco.ballesio@nokia.com>
  22. * Felipe Contreras <felipe.contreras@nokia.com>
  23. *
  24. * This library is free software; you can redistribute it and/or
  25. @@ -384,3 +385,242 @@ not_enough_data:
  26. bail:
  27. return FALSE;
  28. }
  29. +
  30. +/* From mpeg4videoparse */
  31. +/* Used for parsing frame size from codec data */
  32. +typedef struct
  33. +{
  34. + const guint8 *data;
  35. + /* byte offset */
  36. + gsize offset;
  37. + /* bit offset */
  38. + gsize b_offset;
  39. + /* size in bytes */
  40. + gsize size;
  41. +} bitstream_t;
  42. +
  43. +static gboolean
  44. +get_bits (bitstream_t * b, int num, guint32 * bits)
  45. +{
  46. + *bits = 0;
  47. +
  48. + if (b->offset + ((b->b_offset + num) / 8) > b->size)
  49. + return FALSE;
  50. +
  51. + if (b->b_offset + num <= 8) {
  52. + *bits = b->data[b->offset];
  53. + *bits = (*bits >> (8 - num - b->b_offset)) & (((1 << num)) - 1);
  54. +
  55. + b->offset += (b->b_offset + num) / 8;
  56. + b->b_offset = (b->b_offset + num) % 8;
  57. + return TRUE;
  58. + } else {
  59. + /* going over the edge.. */
  60. + int next;
  61. +
  62. + next = (8 - b->b_offset);
  63. + do {
  64. + guint32 t;
  65. +
  66. + if (!get_bits (b, next, &t))
  67. + return FALSE;
  68. + *bits <<= next;
  69. + *bits |= t;
  70. + num -= next;
  71. + next = MIN (8, num);
  72. + } while (num > 0);
  73. +
  74. + return TRUE;
  75. + }
  76. +}
  77. +
  78. +#define GET_BITS(b, num, bits) G_STMT_START { \
  79. + if (!get_bits(b, num, bits)) \
  80. + goto failed; \
  81. +} G_STMT_END
  82. +
  83. +#define MARKER_BIT(b) G_STMT_START { \
  84. + guint32 i; \
  85. + GET_BITS(b, 1, &i); \
  86. + if (i != 0x1) \
  87. + goto failed; \
  88. +} G_STMT_END
  89. +
  90. +static inline gboolean
  91. +next_start_code (bitstream_t * b)
  92. +{
  93. + guint32 bits;
  94. +
  95. + GET_BITS (b, 1, &bits);
  96. + if (bits != 0)
  97. + goto failed;
  98. +
  99. + while (b->b_offset != 0) {
  100. + GET_BITS (b, 1, &bits);
  101. + if (bits != 0x1)
  102. + goto failed;
  103. + }
  104. +
  105. + return TRUE;
  106. +
  107. +failed:
  108. + return FALSE;
  109. +}
  110. +
  111. +gboolean
  112. +gst_dsp_mpeg4_parse(GstDspBase* base, GstBuffer *buf)
  113. +{
  114. + guint32 bits;
  115. + bitstream_t bs;
  116. + guint8 *codec_data;
  117. + guint codec_data_size;
  118. + guint16 time_increment_resolution;
  119. + guint16 width, height;
  120. +
  121. + codec_data = GST_BUFFER_DATA (buf);
  122. + codec_data_size = GST_BUFFER_SIZE (buf);
  123. +
  124. + bs.data = codec_data;
  125. + bs.size = codec_data_size;
  126. + bs.offset = 0;
  127. + bs.b_offset = 0;
  128. +
  129. + /* Expect Visual Object Sequence startcode (0x000001B0) */
  130. + GET_BITS (&bs, 32, &bits);
  131. + if (bits != 0x1B0)
  132. + goto failed;
  133. +
  134. + /* profile and level indication */
  135. + GET_BITS (&bs, 8, &bits);
  136. + if (bits == 0)
  137. + goto failed;
  138. +
  139. + /* Expect Visual Object startcode (0x000001B5) */
  140. + GET_BITS (&bs, 32, &bits);
  141. + if (bits != 0x1B5)
  142. + goto failed;
  143. +
  144. + GET_BITS (&bs, 1, &bits);
  145. + if (bits == 0x1) {
  146. + /* Skip visual_object_verid and priority */
  147. + GET_BITS (&bs, 7, &bits);
  148. + }
  149. +
  150. + GET_BITS (&bs, 4, &bits);
  151. + /* Only support video ID */
  152. + if (bits != 0x1)
  153. + goto failed;
  154. +
  155. + /* video signal type */
  156. + GET_BITS (&bs, 1, &bits);
  157. +
  158. + if (bits == 0x1) {
  159. + /* video signal type, ignore format and range */
  160. + GET_BITS (&bs, 4, &bits);
  161. +
  162. + GET_BITS (&bs, 1, &bits);
  163. + if (bits == 0x1) {
  164. + /* ignore color description */
  165. + GET_BITS (&bs, 24, &bits);
  166. + }
  167. + }
  168. +
  169. + if (!next_start_code (&bs))
  170. + goto failed;
  171. +
  172. + /* expecting a video object startcode */
  173. + GET_BITS (&bs, 32, &bits);
  174. + if (bits > 0x11F)
  175. + goto failed;
  176. +
  177. + /* expecting a video object layer startcode */
  178. + GET_BITS (&bs, 32, &bits);
  179. + if (bits < 0x120 || bits > 0x12F)
  180. + goto failed;
  181. +
  182. + /* ignore random accessible vol and video object type indication */
  183. + GET_BITS (&bs, 9, &bits);
  184. +
  185. + GET_BITS (&bs, 1, &bits);
  186. + if (bits) {
  187. + /* skip video object layer verid and priority */
  188. + GET_BITS (&bs, 7, &bits);
  189. + }
  190. +
  191. + /* aspect ratio info */
  192. + GET_BITS (&bs, 4, &bits);
  193. + if (bits == 0)
  194. + goto failed;
  195. +
  196. + /* check if aspect ratio info is extended par */
  197. + if (bits == 0xff) {
  198. + /* aspect_ratio_width */
  199. + GET_BITS (&bs, 4, &bits);
  200. + /* aspect_ratio_height */
  201. + GET_BITS (&bs, 4, &bits);
  202. + } else if (bits < 0x6) {
  203. + /* get aspect ratio width and height from aspect ratio table */
  204. + }
  205. +
  206. + GET_BITS (&bs, 1, &bits);
  207. + if (bits) {
  208. + /* vol control parameters, skip chroma and low delay */
  209. + GET_BITS (&bs, 3, &bits);
  210. + GET_BITS (&bs, 1, &bits);
  211. + if (bits) {
  212. + /* skip vbv_parameters */
  213. + GET_BITS (&bs, 79, &bits);
  214. + }
  215. + }
  216. +
  217. + /* layer shape */
  218. + GET_BITS (&bs, 2, &bits);
  219. + /* only support rectangular */
  220. + if (bits != 0)
  221. + goto failed;
  222. +
  223. + MARKER_BIT (&bs);
  224. + GET_BITS (&bs, 16, &bits);
  225. + time_increment_resolution = bits;
  226. + MARKER_BIT (&bs);
  227. +
  228. + GET_BITS (&bs, 1, &bits);
  229. + if (bits) {
  230. + /* fixed time increment */
  231. + int n;
  232. +
  233. + /* Lenght of the time increment is the minimal number of bits needed to
  234. + * represent time_increment_resolution */
  235. + for (n = 0; (time_increment_resolution >> n) != 0; n++);
  236. + GET_BITS (&bs, n, &bits);
  237. + /* fixed_time_increment = bits; */
  238. + } else {
  239. + /* fixed_time_increment = 1; */
  240. + }
  241. +
  242. + /* assuming rectangular shape */
  243. + MARKER_BIT (&bs);
  244. + GET_BITS (&bs, 13, &bits);
  245. + if (bits == 0)
  246. + goto failed;
  247. + width = bits;
  248. +
  249. + MARKER_BIT (&bs);
  250. + GET_BITS (&bs, 13, &bits);
  251. + if (bits == 0)
  252. + goto failed;
  253. + height = bits;
  254. + MARKER_BIT (&bs);
  255. +
  256. + pr_debug (base, "width=%u, height=%u", width, height);
  257. +
  258. + set_framesize(base, width, height);
  259. + return TRUE;
  260. +
  261. + /* ERRORS */
  262. +failed:
  263. + {
  264. + GST_DEBUG_OBJECT (base, "Could not parse MPEG4 codec data");
  265. + return FALSE;
  266. + }
  267. +}
  268. diff --git a/gstdspparse.h b/gstdspparse.h
  269. index cbaf711..c06abea 100644
  270. --- a/gstdspparse.h
  271. +++ b/gstdspparse.h
  272. @@ -26,5 +26,6 @@
  273. gboolean gst_dsp_h263_parse(GstDspBase *base, GstBuffer *buf);
  274. gboolean gst_dsp_h264_parse(GstDspBase *base, GstBuffer *buf);
  275. +gboolean gst_dsp_mpeg4_parse(GstDspBase *base, GstBuffer *buf);
  276. #endif
  277. diff --git a/gstdspvdec.c b/gstdspvdec.c
  278. index b842bbd..f4cd0a7 100644
  279. --- a/gstdspvdec.c
  280. +++ b/gstdspvdec.c
  281. @@ -1008,8 +1008,10 @@ sink_setcaps(GstPad *pad,
  282. self->wmv_is_vc1 = FALSE;
  283. }
  284. }
  285. - else
  286. + else {
  287. base->alg = GSTDSP_MPEG4VDEC;
  288. + base->parse_func = gst_dsp_mpeg4_parse;
  289. + }
  290. out_caps = gst_caps_new_empty();