gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/src/ffmpegcolorspace.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer
       
     2  *
       
     3  * unit test for ffmpegcolorspace
       
     4  *
       
     5  * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 #ifdef HAVE_CONFIG_H
       
    24 # include <config.h>
       
    25 #endif
       
    26 
       
    27 #ifdef HAVE_VALGRIND
       
    28 # include <valgrind/valgrind.h>
       
    29 #endif
       
    30 
       
    31 #include <unistd.h>
       
    32 
       
    33 #include <gst/check/gstcheck.h>
       
    34 
       
    35 #include <gst/gst_global.h>
       
    36 
       
    37 #include <unistd.h>
       
    38 
       
    39 #include <gstcheck.h>
       
    40 
       
    41 #define LOG_FILE "c:\\logs\\ffmpegcolorspace_logs.txt" 
       
    42 #include "std_log_result.h" 
       
    43 #define LOG_FILENAME_LINE __FILE__, __LINE__
       
    44 
       
    45 void create_xml(int result)
       
    46 {
       
    47 
       
    48     if(result)
       
    49     {
       
    50         assert_failed = 1;
       
    51     } 
       
    52 
       
    53     testResultXml(xmlfile);
       
    54     close_log_file();
       
    55 
       
    56     if(result)
       
    57     {
       
    58         exit (-1);
       
    59     }    
       
    60 
       
    61 }
       
    62 
       
    63 typedef struct _RGBFormat
       
    64 {
       
    65   const gchar *nick;
       
    66   guint bpp, depth;
       
    67   guint32 red_mask, green_mask, blue_mask, alpha_mask;
       
    68   guint endianness;
       
    69 } RGBFormat;
       
    70 
       
    71 typedef struct _RGBConversion
       
    72 {
       
    73   RGBFormat from_fmt;
       
    74   RGBFormat to_fmt;
       
    75   GstCaps *from_caps;
       
    76   GstCaps *to_caps;
       
    77 } RGBConversion;
       
    78 
       
    79 static GstCaps *
       
    80 rgb_format_to_caps (RGBFormat * fmt)
       
    81 {
       
    82   GstCaps *caps;
       
    83 
       
    84   g_assert (fmt != NULL);
       
    85   g_assert (fmt->endianness != 0);
       
    86 
       
    87   caps = gst_caps_new_simple ("video/x-raw-rgb",
       
    88       "bpp", G_TYPE_INT, fmt->bpp,
       
    89       "depth", G_TYPE_INT, fmt->depth,
       
    90       "red_mask", G_TYPE_INT, fmt->red_mask,
       
    91       "green_mask", G_TYPE_INT, fmt->green_mask,
       
    92       "blue_mask", G_TYPE_INT, fmt->blue_mask,
       
    93       "width", G_TYPE_INT, 16, "height", G_TYPE_INT, 16,
       
    94       "endianness", G_TYPE_INT, fmt->endianness,
       
    95       "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
       
    96 
       
    97   fail_unless (fmt->alpha_mask == 0 || fmt->bpp == 32);
       
    98 
       
    99   if (fmt->alpha_mask != 0) {
       
   100     gst_structure_set (gst_caps_get_structure (caps, 0),
       
   101         "alpha_mask", G_TYPE_INT, fmt->alpha_mask, NULL);
       
   102   }
       
   103 
       
   104   return caps;
       
   105 }
       
   106 
       
   107 static GList *
       
   108 create_rgb_conversions (void)
       
   109 {
       
   110   const RGBFormat rgb_formats[] = {
       
   111     {
       
   112         "RGBA", 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0}, {
       
   113         "ARGB", 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, 0}, {
       
   114         "BGRA", 32, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff, 0}, {
       
   115         "ABGR", 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, 0}, {
       
   116         "RGBx", 32, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000, 0}, {
       
   117         "xRGB", 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, {
       
   118         "BGRx", 32, 24, 0x0000ff00, 0x00ff0000, 0xff000000, 0x00000000, 0}, {
       
   119         "xBGR", 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, {
       
   120         "RGB ", 24, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, {
       
   121         "BGR ", 24, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, {
       
   122         "RGB565", 16, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, 0}, {
       
   123         "xRGB1555", 16, 15, 0x00007c00, 0x000003e0, 0x0000001f, 0x0000000, 0}
       
   124   };
       
   125   const struct
       
   126   {
       
   127     guint from_endianness, to_endianness;
       
   128   } end_arr[4] = {
       
   129     {
       
   130     G_LITTLE_ENDIAN, G_LITTLE_ENDIAN}, {
       
   131     G_BIG_ENDIAN, G_LITTLE_ENDIAN}, {
       
   132     G_LITTLE_ENDIAN, G_BIG_ENDIAN}, {
       
   133     G_BIG_ENDIAN, G_BIG_ENDIAN}
       
   134   };
       
   135   GList *conversions = NULL;
       
   136   guint from_fmt, to_fmt;
       
   137 
       
   138   for (from_fmt = 0; from_fmt < G_N_ELEMENTS (rgb_formats); ++from_fmt) {
       
   139     for (to_fmt = 0; to_fmt < G_N_ELEMENTS (rgb_formats); ++to_fmt) {
       
   140       guint i;
       
   141 
       
   142       for (i = 0; i < 4; ++i) {
       
   143         RGBConversion *conversion;
       
   144 
       
   145         conversion = g_new0 (RGBConversion, 1);
       
   146         conversion->from_fmt = rgb_formats[from_fmt];
       
   147         conversion->to_fmt = rgb_formats[to_fmt];
       
   148         conversion->from_fmt.endianness = end_arr[i].from_endianness;
       
   149         conversion->to_fmt.endianness = end_arr[i].to_endianness;
       
   150         conversion->from_caps = rgb_format_to_caps (&conversion->from_fmt);
       
   151         conversion->to_caps = rgb_format_to_caps (&conversion->to_fmt);
       
   152         conversions = g_list_prepend (conversions, conversion);
       
   153       }
       
   154     }
       
   155   }
       
   156 
       
   157   return g_list_reverse (conversions);
       
   158 }
       
   159 
       
   160 static void
       
   161 rgb_conversion_free (RGBConversion * conv)
       
   162 {
       
   163   gst_caps_unref (conv->from_caps);
       
   164   gst_caps_unref (conv->to_caps);
       
   165   memset (conv, 0x99, sizeof (RGBConversion));
       
   166   g_free (conv);
       
   167 }
       
   168 
       
   169 static guint32
       
   170 right_shift_colour (guint32 mask, guint32 pixel)
       
   171 {
       
   172   if (mask == 0)
       
   173     return 0;
       
   174 
       
   175   pixel = pixel & mask;
       
   176   while ((mask & 0x01) == 0) {
       
   177     mask = mask >> 1;
       
   178     pixel = pixel >> 1;
       
   179   }
       
   180 
       
   181   return pixel;
       
   182 }
       
   183 
       
   184 static guint8
       
   185 fix_expected_colour (guint32 col_mask, guint8 col_expected)
       
   186 {
       
   187   guint32 mask;
       
   188   gint last = g_bit_nth_msf (col_mask, -1);
       
   189   gint first = g_bit_nth_lsf (col_mask, -1);
       
   190 
       
   191   mask = 1 << (last - first + 1);
       
   192   mask -= 1;
       
   193 
       
   194   g_assert (col_expected == 0x00 || col_expected == 0xff);
       
   195 
       
   196   /* this only works because we only check for all-bits-set or no-bits-set */
       
   197   return col_expected & mask;
       
   198 }
       
   199 
       
   200 static void
       
   201 check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask,
       
   202     guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected,
       
   203     guint8 b_expected, guint endianness, guint bpp, guint depth)
       
   204 {
       
   205   guint32 pixel, red, green, blue, alpha;
       
   206 
       
   207   switch (bpp) {
       
   208     case 32:{
       
   209       if (endianness == G_LITTLE_ENDIAN)
       
   210         pixel = GST_READ_UINT32_LE (pixels);
       
   211       else
       
   212         pixel = GST_READ_UINT32_BE (pixels);
       
   213       break;
       
   214     }
       
   215     case 24:{
       
   216       if (endianness == G_BIG_ENDIAN) {
       
   217         pixel = (GST_READ_UINT8 (pixels) << 16) |
       
   218             (GST_READ_UINT8 (pixels + 1) << 8) |
       
   219             (GST_READ_UINT8 (pixels + 2) << 0);
       
   220       } else {
       
   221         pixel = (GST_READ_UINT8 (pixels + 2) << 16) |
       
   222             (GST_READ_UINT8 (pixels + 1) << 8) |
       
   223             (GST_READ_UINT8 (pixels + 0) << 0);
       
   224       }
       
   225       break;
       
   226     }
       
   227     case 16:{
       
   228       if (endianness == G_LITTLE_ENDIAN)
       
   229         pixel = GST_READ_UINT16_LE (pixels);
       
   230       else
       
   231         pixel = GST_READ_UINT16_BE (pixels);
       
   232       break;
       
   233     }
       
   234     default:
       
   235       g_return_if_reached ();
       
   236   }
       
   237 
       
   238   red = right_shift_colour (r_mask, pixel);
       
   239   green = right_shift_colour (g_mask, pixel);
       
   240   blue = right_shift_colour (b_mask, pixel);
       
   241   alpha = right_shift_colour (a_mask, pixel);
       
   242 
       
   243   /* can't enable this by default, valgrind will complain about accessing
       
   244    * uninitialised memory for the depth=24,bpp=32 formats ... */
       
   245   /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x",
       
   246      pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */
       
   247 
       
   248   /* fix up the mask (for rgb15/16) */
       
   249   if (bpp == 16) {
       
   250     r_expected = fix_expected_colour (r_mask, r_expected);
       
   251     g_expected = fix_expected_colour (g_mask, g_expected);
       
   252     b_expected = fix_expected_colour (b_mask, b_expected);
       
   253   }
       
   254 
       
   255   fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x    "
       
   256       "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", r_expected, red,
       
   257       pixels[0], pixels[1], pixels[2], pixels[3], pixel);
       
   258   fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x    "
       
   259       "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", g_expected, green,
       
   260       pixels[0], pixels[1], pixels[2], pixels[3], pixel);
       
   261   fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x    "
       
   262       "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", b_expected, blue,
       
   263       pixels[0], pixels[1], pixels[2], pixels[3], pixel);
       
   264 
       
   265 //  FIXME: fix alpha check
       
   266 //  fail_unless (a_mask == 0 || alpha != 0);      /* better than nothing */
       
   267 }
       
   268 
       
   269 static void
       
   270 got_buf_cb (GstElement * sink, GstBuffer * new_buf, GstPad * pad,
       
   271     GstBuffer ** p_old_buf)
       
   272 {
       
   273   gst_buffer_replace (p_old_buf, new_buf);
       
   274 }
       
   275 
       
   276 /* Note: lots of this code here is also in the videotestsrc.c unit test */
       
   277 void  test_rgb_to_rgb()
       
   278 {
       
   279   const struct
       
   280   {
       
   281     const gchar *pattern_name;
       
   282     gint pattern_enum;
       
   283     guint8 r_expected;
       
   284     guint8 g_expected;
       
   285     guint8 b_expected;
       
   286   } test_patterns[] = {
       
   287     {
       
   288     "white", 3, 0xff, 0xff, 0xff}, {
       
   289     "red", 4, 0xff, 0x00, 0x00}, {
       
   290     "green", 5, 0x00, 0xff, 0x00}, {
       
   291     "blue", 6, 0x00, 0x00, 0xff}, {
       
   292     "black", 2, 0x00, 0x00, 0x00}
       
   293   };
       
   294   GstElement *pipeline, *src, *filter1, *csp, *filter2, *sink;
       
   295   const GstCaps *template_caps;
       
   296   GstBuffer *buf = NULL;
       
   297   GstPad *srcpad;
       
   298   GList *conversions, *l;
       
   299   gint p;
       
   300 
       
   301   /* test check function */
       
   302   fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22);
       
   303 
       
   304   pipeline = gst_pipeline_new ("pipeline");
       
   305   src = gst_check_setup_element ("videotestsrc");
       
   306   filter1 = gst_check_setup_element ("capsfilter");
       
   307   csp = gst_check_setup_element ("ffmpegcolorspace");
       
   308   filter2 = gst_element_factory_make ("capsfilter", "to_filter");
       
   309   sink = gst_check_setup_element ("fakesink");
       
   310 
       
   311   gst_bin_add_many (GST_BIN (pipeline), src, filter1, csp, filter2, sink, NULL);
       
   312 
       
   313   fail_unless (gst_element_link (src, filter1));
       
   314   fail_unless (gst_element_link (filter1, csp));
       
   315   fail_unless (gst_element_link (csp, filter2));
       
   316   fail_unless (gst_element_link (filter2, sink));
       
   317 
       
   318   srcpad = gst_element_get_pad (src, "src");
       
   319   template_caps = gst_pad_get_pad_template_caps (srcpad);
       
   320   gst_object_unref (srcpad);
       
   321 
       
   322   g_object_set (sink, "signal-handoffs", TRUE, NULL);
       
   323   g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &buf);
       
   324 
       
   325   GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps);
       
   326 
       
   327   conversions = create_rgb_conversions ();
       
   328 
       
   329   for (l = conversions; l != NULL; l = l->next) {
       
   330     RGBConversion *conv = (RGBConversion *) l->data;
       
   331 
       
   332     /* does videotestsrc support the from_caps? */
       
   333     if (!gst_caps_is_subset (conv->from_caps, template_caps)) {
       
   334       GST_DEBUG ("videotestsrc doesn't support from_caps %" GST_PTR_FORMAT,
       
   335           conv->from_caps);
       
   336       continue;
       
   337     }
       
   338 
       
   339     /* caps are supported, let's run some tests then ... */
       
   340     for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) {
       
   341       GstStateChangeReturn state_ret;
       
   342       RGBFormat *from = &conv->from_fmt;
       
   343       RGBFormat *to = &conv->to_fmt;
       
   344 
       
   345       /* trick compiler into thinking from is used, might throw warning
       
   346        * otherwise if the debugging system is disabled */
       
   347       fail_unless (from != NULL);
       
   348 
       
   349       gst_element_set_state (pipeline, GST_STATE_NULL);
       
   350 
       
   351       g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL);
       
   352 
       
   353       GST_INFO ("%5s %u/%u %08x %08x %08x %08x %u => "
       
   354           "%5s %u/%u %08x %08x %08x %08x %u, pattern=%s",
       
   355           from->nick, from->bpp, from->depth, from->red_mask,
       
   356           from->green_mask, from->blue_mask, from->alpha_mask,
       
   357           from->endianness, to->nick, to->bpp, to->depth, to->red_mask,
       
   358           to->green_mask, to->blue_mask, to->alpha_mask, to->endianness,
       
   359           test_patterns[p].pattern_name);
       
   360 
       
   361       /* now get videotestsrc to produce a buffer with the given caps */
       
   362       g_object_set (filter1, "caps", conv->from_caps, NULL);
       
   363 
       
   364       /* ... and force ffmpegcolorspace to convert to our target caps */
       
   365       g_object_set (filter2, "caps", conv->to_caps, NULL);
       
   366 
       
   367       state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
       
   368       if (state_ret == GST_STATE_CHANGE_FAILURE) {
       
   369         GstMessage *msg;
       
   370         GError *err = NULL;
       
   371 
       
   372         msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_ERROR, 0);
       
   373         fail_if (msg == NULL, "expected ERROR message on the bus");
       
   374         fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
       
   375         gst_message_parse_error (msg, &err, NULL);
       
   376         fail_unless (err != NULL);
       
   377         if (msg->src == GST_OBJECT_CAST (src) &&
       
   378             err->code == GST_STREAM_ERROR_FORMAT) {
       
   379           GST_DEBUG ("ffmpegcolorspace does not support this conversion");
       
   380           gst_message_unref (msg);
       
   381           g_error_free (err);
       
   382           continue;
       
   383         }
       
   384         fail_unless (state_ret != GST_STATE_CHANGE_FAILURE,
       
   385             "pipeline _set_state() to PAUSED failed: %s", err->message);
       
   386       }
       
   387 
       
   388       state_ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
       
   389      fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS,
       
   390           "pipeline failed going to PAUSED state");
       
   391 
       
   392       state_ret = gst_element_set_state (pipeline, GST_STATE_NULL);
       
   393      fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
       
   394 
       
   395       fail_unless (buf != NULL);
       
   396 
       
   397       /* check buffer caps */
       
   398       {
       
   399         GstStructure *s;
       
   400         gint v;
       
   401 
       
   402         fail_unless (GST_BUFFER_CAPS (buf) != NULL);
       
   403         s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
       
   404         fail_unless (gst_structure_get_int (s, "bpp", &v));
       
   405         fail_unless_equals_int (v, to->bpp);
       
   406         fail_unless (gst_structure_get_int (s, "depth", &v));
       
   407         fail_unless_equals_int (v, to->depth);
       
   408         fail_unless (gst_structure_get_int (s, "red_mask", &v));
       
   409         fail_unless_equals_int (v, to->red_mask);
       
   410         fail_unless (gst_structure_get_int (s, "green_mask", &v));
       
   411         fail_unless_equals_int (v, to->green_mask);
       
   412         fail_unless (gst_structure_get_int (s, "blue_mask", &v));
       
   413         fail_unless_equals_int (v, to->blue_mask);
       
   414         /* there mustn't be an alpha_mask if there's no alpha component */
       
   415         if (to->depth == 32) {
       
   416           fail_unless (gst_structure_get_int (s, "alpha_mask", &v));
       
   417           fail_unless_equals_int (v, to->alpha_mask);
       
   418         } else {
       
   419           fail_unless (gst_structure_get_value (s, "alpha_mask") == NULL);
       
   420         }
       
   421       }
       
   422 
       
   423       /* now check the top-left pixel */
       
   424       check_rgb_buf (GST_BUFFER_DATA (buf), to->red_mask,
       
   425           to->green_mask, to->blue_mask, to->alpha_mask,
       
   426           test_patterns[p].r_expected, test_patterns[p].g_expected,
       
   427           test_patterns[p].b_expected, to->endianness, to->bpp, to->depth);
       
   428 
       
   429       gst_buffer_unref (buf);
       
   430       buf = NULL;
       
   431     }
       
   432   }
       
   433 
       
   434   g_list_foreach (conversions, (GFunc) rgb_conversion_free, NULL);
       
   435   g_list_free (conversions);
       
   436 
       
   437   gst_element_set_state (pipeline, GST_STATE_NULL);
       
   438   gst_object_unref (pipeline);
       
   439   std_log(LOG_FILENAME_LINE, "Test Successful");
       
   440   create_xml(0);
       
   441 }
       
   442 
       
   443 //GST_END_TEST;
       
   444 
       
   445 /*static Suite *
       
   446 ffmpegcolorspace_suite (void)
       
   447 {
       
   448   Suite *s = suite_create ("ffmpegcolorspace");
       
   449   TCase *tc_chain = tcase_create ("general");
       
   450 
       
   451   suite_add_tcase (s, tc_chain);
       
   452 
       
   453 #ifdef HAVE_VALGRIND
       
   454   if (RUNNING_ON_VALGRIND) {
       
   455     otherwise valgrind errors out when liboil probes CPU extensions
       
   456      during which it causes SIGILLs etc. to be fired 
       
   457     g_setenv ("OIL_CPU_FLAGS", "0", 0);
       
   458     test_rgb_formats takes a bit longer, so increase timeout 
       
   459     tcase_set_timeout (tc_chain, 10 * 60);
       
   460   }
       
   461 #endif
       
   462 
       
   463   FIXME: add tests for YUV <=> YUV and YUV <=> RGB 
       
   464   tcase_add_test (tc_chain, test_rgb_to_rgb);
       
   465 
       
   466   return s;
       
   467 }*/
       
   468 void (*fn[]) (void) = {
       
   469         test_rgb_to_rgb
       
   470 
       
   471 };
       
   472 
       
   473 char *args[] = {
       
   474         "test_rgb_to_rgb"
       
   475 
       
   476 };
       
   477 /*void main()
       
   478     {
       
   479     gst_init (NULL, NULL);
       
   480     test_rgb_to_rgb();
       
   481  
       
   482     }*/
       
   483 GST_CHECK_MAIN (ffmpegcolorspace);