td_wmvdec.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Copyright (C) 2009-2010 Felipe Contreras
  3. * Copyright (C) 2009-2010 Nokia Corporation
  4. *
  5. * Authors:
  6. * Felipe Contreras <felipe.contreras@gmail.com>
  7. * Juha Alanen <juha.m.alanen@nokia.com>
  8. *
  9. * This file may be used under the terms of the GNU Lesser General Public
  10. * License version 2.1, a copy of which is found in LICENSE included in the
  11. * packaging of this file.
  12. */
  13. #include "dsp_bridge.h"
  14. #include "dmm_buffer.h"
  15. #include "gstdspbase.h"
  16. #include "gstdspvdec.h"
  17. struct create_args {
  18. uint32_t size;
  19. uint16_t num_streams;
  20. uint16_t in_id;
  21. uint16_t in_type;
  22. uint16_t in_count;
  23. uint16_t out_id;
  24. uint16_t out_type;
  25. uint16_t out_count;
  26. uint16_t reserved;
  27. uint32_t max_width;
  28. uint32_t max_height;
  29. uint32_t color_format;
  30. uint32_t max_framerate;
  31. uint32_t max_bitrate;
  32. uint32_t endianness;
  33. int32_t profile;
  34. int32_t max_level;
  35. uint32_t process_mode;
  36. int32_t preroll;
  37. uint32_t stream_format;
  38. uint32_t stride_width;
  39. };
  40. static void create_args(GstDspBase *base, unsigned *profile_id, void **arg_data)
  41. {
  42. GstDspVDec *self = GST_DSP_VDEC(base);
  43. struct create_args args = {
  44. .size = sizeof(args) - 4,
  45. .num_streams = 2,
  46. .in_id = 0,
  47. .in_type = 0,
  48. .in_count = base->ports[0]->num_buffers,
  49. .out_id = 1,
  50. .out_type = 0,
  51. .out_count = base->ports[1]->num_buffers,
  52. .max_width = self->width,
  53. .max_height = self->height,
  54. .color_format = self->color_format == GST_MAKE_FOURCC('U', 'Y', 'V', 'Y') ? 4 : 1,
  55. .endianness = 1,
  56. .profile = -1,
  57. .max_level = -1,
  58. .stream_format = self->wmv_is_vc1 ? 1 : 2, /* 1 = wvc1, 2 = wmv3 */
  59. };
  60. if (self->width * self->height > 640 * 480)
  61. *profile_id = 4;
  62. else if (self->width * self->height > 352 * 288)
  63. *profile_id = 3;
  64. else if (self->width * self->height > 176 * 144)
  65. *profile_id = 2;
  66. else
  67. *profile_id = 1;
  68. *arg_data = malloc(sizeof(args));
  69. memcpy(*arg_data, &args, sizeof(args));
  70. }
  71. struct in_params {
  72. int32_t buf_count;
  73. uint32_t frame_index;
  74. };
  75. struct out_params {
  76. uint32_t display_id;
  77. uint32_t bytes_consumed;
  78. int32_t error_code;
  79. uint32_t frame_type;
  80. };
  81. struct dyn_params {
  82. int32_t size;
  83. uint32_t decode_header;
  84. uint32_t display_width;
  85. uint32_t frame_skip_mode;
  86. uint32_t pp_type;
  87. uint16_t stream_format;
  88. };
  89. struct rcv_struct {
  90. uint32_t num_frames:24;
  91. uint32_t frame_type:8;
  92. uint32_t id;
  93. uint32_t codec_data;
  94. uint32_t height;
  95. uint32_t width;
  96. };
  97. static inline void send_rcv_buffer(GstDspBase *base, GstBuffer *buf)
  98. {
  99. GstDspVDec *self;
  100. GstBuffer *rcv_buf;
  101. struct rcv_struct *rcv_struct;
  102. guint8 *codec_data;
  103. self = GST_DSP_VDEC(base);
  104. rcv_buf = gst_buffer_new_and_alloc(sizeof(*rcv_struct));
  105. rcv_struct = (struct rcv_struct *) GST_BUFFER_DATA(rcv_buf);
  106. codec_data = GST_BUFFER_DATA(buf);
  107. rcv_struct->num_frames = 0xFFFFFF;
  108. rcv_struct->frame_type = 0x85;
  109. rcv_struct->id = 0x04;
  110. rcv_struct->codec_data = codec_data[0] << 0 |
  111. codec_data[1] << 8 |
  112. codec_data[2] << 16 |
  113. codec_data[3] << 24;
  114. rcv_struct->height = self->height;
  115. rcv_struct->width = self->width;
  116. (void) gstdsp_send_codec_data(base, rcv_buf);
  117. gst_buffer_unref(rcv_buf);
  118. }
  119. static inline void prefix_vc1(GstDspVDec *self, struct td_buffer *tb)
  120. {
  121. guint8 *input_data, *output_data, *alloc_data;
  122. gint input_size, output_size;
  123. dmm_buffer_t *b = tb->data;
  124. input_data = b->data;
  125. input_size = b->len;
  126. /* save this so it is not freed by subsequent allocate */
  127. alloc_data = b->allocated_data;
  128. b->allocated_data = NULL;
  129. if (G_LIKELY(self->codec_data_sent)) {
  130. output_size = input_size + 4;
  131. dmm_buffer_allocate(b, output_size);
  132. output_data = b->data;
  133. /* prefix buffer with 0x0000010d */
  134. GST_WRITE_UINT32_BE(output_data, 0x10d);
  135. output_data += 4;
  136. memcpy(output_data, input_data, input_size);
  137. } else {
  138. GstDspBase *base = GST_DSP_BASE(self);
  139. GstBuffer *buf = base->codec_data;
  140. base->codec_data = NULL;
  141. output_size = GST_BUFFER_SIZE(buf) + 4 + input_size;
  142. dmm_buffer_allocate(b, output_size);
  143. output_data = b->data;
  144. /* copy codec data to the beginning of the first buffer */
  145. memcpy(output_data, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
  146. output_data += GST_BUFFER_SIZE(buf);
  147. /* prefix frame data with 0x0000010d */
  148. GST_WRITE_UINT32_BE(output_data, 0x10d);
  149. output_data += 4;
  150. memcpy(output_data, input_data, input_size);
  151. self->codec_data_sent = TRUE;
  152. gst_buffer_unref(buf);
  153. }
  154. /* release original data */
  155. if (tb->user_data) {
  156. gst_buffer_unref(tb->user_data);
  157. tb->user_data = NULL;
  158. }
  159. g_free(alloc_data);
  160. return;
  161. }
  162. static void in_send_cb(GstDspBase *base, struct td_buffer *tb)
  163. {
  164. GstDspVDec *self = GST_DSP_VDEC(base);
  165. struct in_params *param;
  166. param = tb->params->data;
  167. uint32_t vc1_startcode = *(uint32_t *)tb->data->data;
  168. if ((vc1_startcode & 0x00FFFFFF) == 0x010000 && (vc1_startcode >> 24 >= 0x0A)
  169. && (vc1_startcode >> 24 <= 0x1F))
  170. self->codec_data_sent = TRUE;
  171. else if (self->wmv_is_vc1)
  172. prefix_vc1(self, tb);
  173. param->frame_index = g_atomic_int_exchange_and_add(&self->frame_index, 1);
  174. }
  175. static void out_recv_cb(GstDspBase *base, struct td_buffer *tb)
  176. {
  177. GstDspVDec *self = GST_DSP_VDEC(base);
  178. struct out_params *param;
  179. param = tb->params->data;
  180. if (param->frame_type == 0xFFFFFFFF)
  181. pr_warning(self, "empty frame received, frame number: %d",
  182. param->display_id);
  183. if (param->error_code != 0)
  184. pr_debug(self, "error in decoding: 0x%x, frame number: %d frame type: %u",
  185. param->error_code, param->display_id, param->frame_type);
  186. gstdsp_vdec_len_fixup(self, tb->data);
  187. }
  188. static void setup_params(GstDspBase *base)
  189. {
  190. GstDspVDec *self = GST_DSP_VDEC(base);
  191. struct in_params *in_param;
  192. struct out_params *out_param;
  193. du_port_t *p;
  194. self->frame_index = 1;
  195. p = base->ports[0];
  196. gstdsp_port_setup_params(base, p, sizeof(*in_param), NULL);
  197. p->send_cb = in_send_cb;
  198. p = base->ports[1];
  199. gstdsp_port_setup_params(base, p, sizeof(*out_param), NULL);
  200. p->recv_cb = out_recv_cb;
  201. }
  202. static bool handle_extra_data(GstDspBase *base, GstBuffer *buf)
  203. {
  204. GstDspVDec *self = GST_DSP_VDEC(base);
  205. if (self->wmv_is_vc1)
  206. base->codec_data = gst_buffer_ref(buf);
  207. else
  208. send_rcv_buffer(base, buf);
  209. return true;
  210. }
  211. static void send_params(GstDspBase *base, struct dsp_node *node)
  212. {
  213. struct dyn_params *params;
  214. dmm_buffer_t *b;
  215. GstDspVDec *self = GST_DSP_VDEC(base);
  216. b = dmm_buffer_calloc(base->dsp_handle, base->proc,
  217. sizeof(*params), DMA_TO_DEVICE);
  218. params = b->data;
  219. params->size = (int32_t) sizeof(*params);
  220. params->stream_format = self->wmv_is_vc1 ? 1 : 2;
  221. gstdsp_send_alg_ctrl(base, node, b);
  222. }
  223. struct td_codec td_wmvdec_codec = {
  224. .uuid = &(const struct dsp_uuid) { 0x609DAB97, 0x3DFC, 0x471F, 0x8A, 0xB9,
  225. { 0x4E, 0x56, 0xE8, 0x34, 0x50, 0x1B } },
  226. .filename = "wmv9dec_sn.dll64P",
  227. .setup_params = setup_params,
  228. .create_args = create_args,
  229. .handle_extra_data = handle_extra_data,
  230. .send_params = send_params,
  231. .flush_buffer = gstdsp_base_flush_buffer,
  232. };