LCOV - code coverage report
Current view: top level - gst/flx - gstflxdec.c (source / functions) Hit Total Coverage
Test: GStreamer Good Plug-ins 0.10.28.1 Lines: 59 291 20.3 %
Date: 2011-03-25 Functions: 7 16 43.8 %
Branches: 14 166 8.4 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
       3                 :            :  *
       4                 :            :  * This library is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU Library General Public
       6                 :            :  * License as published by the Free Software Foundation; either
       7                 :            :  * version 2 of the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * This library is distributed in the hope that it will be useful,
      10                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12                 :            :  * Library General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Library General Public
      15                 :            :  * License along with this library; if not, write to the
      16                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17                 :            :  * Boston, MA 02111-1307, USA.
      18                 :            :  */
      19                 :            : /**
      20                 :            :  * SECTION:element-flxdec
      21                 :            :  *
      22                 :            :  * This element decodes fli/flc/flx-video into raw video
      23                 :            :  */
      24                 :            : /*
      25                 :            :  * http://www.coolutils.com/Formats/FLI
      26                 :            :  * http://woodshole.er.usgs.gov/operations/modeling/flc.html
      27                 :            :  */
      28                 :            : 
      29                 :            : #ifdef HAVE_CONFIG_H
      30                 :            : #include "config.h"
      31                 :            : #endif
      32                 :            : #include <string.h>
      33                 :            : 
      34                 :            : #include "flx_fmt.h"
      35                 :            : #include "gstflxdec.h"
      36                 :            : #include <gst/video/video.h>
      37                 :            : 
      38                 :            : #define JIFFIE  (GST_SECOND/70)
      39                 :            : 
      40                 :            : GST_DEBUG_CATEGORY_STATIC (flxdec_debug);
      41                 :            : #define GST_CAT_DEFAULT flxdec_debug
      42                 :            : 
      43                 :            : /* input */
      44                 :            : static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
      45                 :            :     GST_PAD_SINK,
      46                 :            :     GST_PAD_ALWAYS,
      47                 :            :     GST_STATIC_CAPS ("video/x-fli")
      48                 :            :     );
      49                 :            : 
      50                 :            : /* output */
      51                 :            : static GstStaticPadTemplate src_video_factory = GST_STATIC_PAD_TEMPLATE ("src",
      52                 :            :     GST_PAD_SRC,
      53                 :            :     GST_PAD_ALWAYS,
      54                 :            :     GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN)
      55                 :            :     );
      56                 :            : 
      57                 :            : 
      58                 :            : static void gst_flxdec_class_init (GstFlxDecClass * klass);
      59                 :            : static void gst_flxdec_base_init (GstFlxDecClass * klass);
      60                 :            : static void gst_flxdec_init (GstFlxDec * flxdec);
      61                 :            : static void gst_flxdec_dispose (GstFlxDec * flxdec);
      62                 :            : 
      63                 :            : static GstFlowReturn gst_flxdec_chain (GstPad * pad, GstBuffer * buf);
      64                 :            : 
      65                 :            : static GstStateChangeReturn gst_flxdec_change_state (GstElement * element,
      66                 :            :     GstStateChange transition);
      67                 :            : 
      68                 :            : static gboolean gst_flxdec_src_query_handler (GstPad * pad, GstQuery * query);
      69                 :            : static gboolean gst_flxdec_src_event_handler (GstPad * pad, GstEvent * event);
      70                 :            : static gboolean gst_flxdec_sink_event_handler (GstPad * pad, GstEvent * event);
      71                 :            : 
      72                 :            : static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
      73                 :            : static void flx_decode_brun (GstFlxDec *, guchar *, guchar *);
      74                 :            : static void flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
      75                 :            : static void flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
      76                 :            : 
      77                 :            : #define rndalign(off) ((off) + ((off) & 1))
      78                 :            : 
      79                 :            : static GstElementClass *parent_class = NULL;
      80                 :            : 
      81                 :            : GType
      82                 :         38 : gst_flxdec_get_type (void)
      83                 :            : {
      84                 :            :   static GType flxdec_type = 0;
      85                 :            : 
      86         [ +  + ]:         38 :   if (!flxdec_type) {
      87                 :            :     static const GTypeInfo flxdec_info = {
      88                 :            :       sizeof (GstFlxDecClass),
      89                 :            :       (GBaseInitFunc) gst_flxdec_base_init,
      90                 :            :       NULL,
      91                 :            :       (GClassInitFunc) gst_flxdec_class_init,
      92                 :            :       NULL,
      93                 :            :       NULL,
      94                 :            :       sizeof (GstFlxDec),
      95                 :            :       0,
      96                 :            :       (GInstanceInitFunc) gst_flxdec_init,
      97                 :            :     };
      98                 :            : 
      99                 :          4 :     flxdec_type =
     100                 :          4 :         g_type_register_static (GST_TYPE_ELEMENT, "GstFlxDec", &flxdec_info, 0);
     101                 :            :   }
     102                 :         38 :   return flxdec_type;
     103                 :            : }
     104                 :            : 
     105                 :            : static void
     106                 :          4 : gst_flxdec_base_init (GstFlxDecClass * klass)
     107                 :            : {
     108                 :          4 :   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
     109                 :            : 
     110                 :          4 :   gst_element_class_set_details_simple (gstelement_class, "FLX video decoder",
     111                 :            :       "Codec/Decoder/Video",
     112                 :            :       "FLC/FLI/FLX video decoder",
     113                 :            :       "Sepp Wijnands <mrrazz@garbage-coderz.net>, Zeeshan Ali <zeenix@gmail.com>");
     114                 :          4 :   gst_element_class_add_pad_template (gstelement_class,
     115                 :            :       gst_static_pad_template_get (&sink_factory));
     116                 :          4 :   gst_element_class_add_pad_template (gstelement_class,
     117                 :            :       gst_static_pad_template_get (&src_video_factory));
     118                 :          4 : }
     119                 :            : 
     120                 :            : static void
     121                 :          4 : gst_flxdec_class_init (GstFlxDecClass * klass)
     122                 :            : {
     123                 :            :   GObjectClass *gobject_class;
     124                 :            :   GstElementClass *gstelement_class;
     125                 :            : 
     126                 :          4 :   gobject_class = (GObjectClass *) klass;
     127                 :          4 :   gstelement_class = (GstElementClass *) klass;
     128                 :            : 
     129                 :          4 :   parent_class = g_type_class_peek_parent (klass);
     130                 :            : 
     131                 :          4 :   gobject_class->dispose = (GObjectFinalizeFunc) gst_flxdec_dispose;
     132                 :            : 
     133         [ +  - ]:          4 :   GST_DEBUG_CATEGORY_INIT (flxdec_debug, "flxdec", 0, "FLX video decoder");
     134                 :            : 
     135                 :          4 :   gstelement_class->change_state = gst_flxdec_change_state;
     136                 :          4 : }
     137                 :            : 
     138                 :            : static void
     139                 :          3 : gst_flxdec_init (GstFlxDec * flxdec)
     140                 :            : {
     141                 :          3 :   flxdec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
     142                 :          3 :   gst_element_add_pad (GST_ELEMENT (flxdec), flxdec->sinkpad);
     143                 :          3 :   gst_pad_set_chain_function (flxdec->sinkpad, gst_flxdec_chain);
     144                 :          3 :   gst_pad_set_event_function (flxdec->sinkpad, gst_flxdec_sink_event_handler);
     145                 :            : 
     146                 :          3 :   flxdec->srcpad = gst_pad_new_from_static_template (&src_video_factory, "src");
     147                 :          3 :   gst_element_add_pad (GST_ELEMENT (flxdec), flxdec->srcpad);
     148                 :          3 :   gst_pad_set_query_function (flxdec->srcpad, gst_flxdec_src_query_handler);
     149                 :          3 :   gst_pad_set_event_function (flxdec->srcpad, gst_flxdec_src_event_handler);
     150                 :            : 
     151                 :          3 :   gst_pad_use_fixed_caps (flxdec->srcpad);
     152                 :            : 
     153                 :          3 :   flxdec->frame = NULL;
     154                 :          3 :   flxdec->delta = NULL;
     155                 :            : 
     156                 :          3 :   flxdec->adapter = gst_adapter_new ();
     157                 :          3 : }
     158                 :            : 
     159                 :            : static void
     160                 :          3 : gst_flxdec_dispose (GstFlxDec * flxdec)
     161                 :            : {
     162         [ +  - ]:          3 :   if (flxdec->adapter) {
     163                 :          3 :     g_object_unref (flxdec->adapter);
     164                 :          3 :     flxdec->adapter = NULL;
     165                 :            :   }
     166                 :            : 
     167                 :          3 :   G_OBJECT_CLASS (parent_class)->dispose ((GObject *) flxdec);
     168                 :          3 : }
     169                 :            : 
     170                 :            : static gboolean
     171                 :          0 : gst_flxdec_src_query_handler (GstPad * pad, GstQuery * query)
     172                 :            : {
     173                 :          0 :   GstFlxDec *flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
     174                 :          0 :   gboolean ret = FALSE;
     175                 :            : 
     176         [ #  # ]:          0 :   switch (GST_QUERY_TYPE (query)) {
     177                 :            :     case GST_QUERY_DURATION:
     178                 :            :     {
     179                 :            :       GstFormat format;
     180                 :            : 
     181                 :          0 :       gst_query_parse_duration (query, &format, NULL);
     182                 :            : 
     183         [ #  # ]:          0 :       if (format != GST_FORMAT_TIME)
     184                 :          0 :         goto done;
     185                 :            : 
     186                 :          0 :       gst_query_set_duration (query, format, flxdec->duration);
     187                 :            : 
     188                 :          0 :       ret = TRUE;
     189                 :            :     }
     190                 :            :     default:
     191                 :          0 :       break;
     192                 :            :   }
     193                 :            : done:
     194                 :          0 :   gst_object_unref (flxdec);
     195                 :            : 
     196                 :          0 :   return ret;
     197                 :            : }
     198                 :            : 
     199                 :            : static gboolean
     200                 :          0 : gst_flxdec_src_event_handler (GstPad * pad, GstEvent * event)
     201                 :            : {
     202                 :          0 :   GstFlxDec *flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
     203                 :            :   gboolean ret;
     204                 :            : 
     205                 :            :   /* TODO: implement the seek and other event handling */
     206                 :            : 
     207                 :          0 :   ret = gst_pad_push_event (flxdec->sinkpad, event);
     208                 :            : 
     209                 :          0 :   gst_object_unref (flxdec);
     210                 :            : 
     211                 :          0 :   return ret;
     212                 :            : }
     213                 :            : 
     214                 :            : static gboolean
     215                 :          0 : gst_flxdec_sink_event_handler (GstPad * pad, GstEvent * event)
     216                 :            : {
     217                 :            :   GstFlxDec *flxdec;
     218                 :            :   gboolean ret;
     219                 :            : 
     220                 :          0 :   flxdec = GST_FLXDEC (gst_pad_get_parent (pad));
     221                 :            : 
     222                 :          0 :   ret = gst_pad_push_event (flxdec->srcpad, event);
     223                 :            : 
     224                 :          0 :   gst_object_unref (flxdec);
     225                 :          0 :   return ret;
     226                 :            : }
     227                 :            : 
     228                 :            : static void
     229                 :          0 : flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
     230                 :            :     guchar * dest)
     231                 :            : {
     232                 :            :   FlxFrameChunk *hdr;
     233                 :            : 
     234         [ #  # ]:          0 :   g_return_if_fail (data != NULL);
     235                 :            : 
     236         [ #  # ]:          0 :   while (count--) {
     237                 :          0 :     hdr = (FlxFrameChunk *) data;
     238                 :            :     FLX_FRAME_CHUNK_FIX_ENDIANNESS (hdr);
     239                 :          0 :     data += FlxFrameChunkSize;
     240                 :            : 
     241   [ #  #  #  #  :          0 :     switch (hdr->id) {
             #  #  #  # ]
     242                 :            :       case FLX_COLOR64:
     243                 :          0 :         flx_decode_color (flxdec, data, dest, 2);
     244                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     245                 :          0 :         break;
     246                 :            : 
     247                 :            :       case FLX_COLOR256:
     248                 :          0 :         flx_decode_color (flxdec, data, dest, 0);
     249                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     250                 :          0 :         break;
     251                 :            : 
     252                 :            :       case FLX_BRUN:
     253                 :          0 :         flx_decode_brun (flxdec, data, dest);
     254                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     255                 :          0 :         break;
     256                 :            : 
     257                 :            :       case FLX_LC:
     258                 :          0 :         flx_decode_delta_fli (flxdec, data, dest);
     259                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     260                 :          0 :         break;
     261                 :            : 
     262                 :            :       case FLX_SS2:
     263                 :          0 :         flx_decode_delta_flc (flxdec, data, dest);
     264                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     265                 :          0 :         break;
     266                 :            : 
     267                 :            :       case FLX_BLACK:
     268                 :          0 :         memset (dest, 0, flxdec->size);
     269                 :          0 :         break;
     270                 :            : 
     271                 :            :       case FLX_MINI:
     272                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     273                 :          0 :         break;
     274                 :            : 
     275                 :            :       default:
     276         [ #  # ]:          0 :         GST_WARNING ("Unimplented chunk type: 0x%02x size: %d - skipping",
     277                 :            :             hdr->id, hdr->size);
     278                 :          0 :         data += rndalign (hdr->size) - FlxFrameChunkSize;
     279                 :          0 :         break;
     280                 :            :     }
     281                 :            :   }
     282                 :            : }
     283                 :            : 
     284                 :            : 
     285                 :            : static void
     286                 :          0 : flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
     287                 :            : {
     288                 :            :   guint packs, count, indx;
     289                 :            : 
     290         [ #  # ]:          0 :   g_return_if_fail (flxdec != NULL);
     291                 :            : 
     292                 :          0 :   packs = (data[0] + (data[1] << 8));
     293                 :            : 
     294                 :          0 :   data += 2;
     295                 :          0 :   indx = 0;
     296                 :            : 
     297         [ #  # ]:          0 :   GST_LOG ("GstFlxDec: cmap packs: %d", packs);
     298         [ #  # ]:          0 :   while (packs--) {
     299                 :            :     /* color map index + skip count */
     300                 :          0 :     indx += *data++;
     301                 :            : 
     302                 :            :     /* number of rgb triplets */
     303                 :          0 :     count = *data++ & 0xff;
     304         [ #  # ]:          0 :     if (count == 0)
     305                 :          0 :       count = 256;
     306                 :            : 
     307         [ #  # ]:          0 :     GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)", count, indx);
     308                 :          0 :     flx_set_palette_vector (flxdec->converter, indx, count, data, scale);
     309                 :            : 
     310                 :          0 :     data += (count * 3);
     311                 :            :   }
     312                 :            : }
     313                 :            : 
     314                 :            : static void
     315                 :          0 : flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
     316                 :            : {
     317                 :            :   gulong count, lines, row;
     318                 :            :   guchar x;
     319                 :            : 
     320         [ #  # ]:          0 :   g_return_if_fail (flxdec != NULL);
     321                 :            : 
     322                 :          0 :   lines = flxdec->hdr.height;
     323         [ #  # ]:          0 :   while (lines--) {
     324                 :            :     /* packet count.  
     325                 :            :      * should not be used anymore, since the flc format can
     326                 :            :      * contain more then 255 RLE packets. we use the frame 
     327                 :            :      * width instead. 
     328                 :            :      */
     329                 :          0 :     data++;
     330                 :            : 
     331                 :          0 :     row = flxdec->hdr.width;
     332         [ #  # ]:          0 :     while (row) {
     333                 :          0 :       count = *data++;
     334                 :            : 
     335         [ #  # ]:          0 :       if (count > 0x7f) {
     336                 :            :         /* literal run */
     337                 :          0 :         count = 0x100 - count;
     338                 :          0 :         row -= count;
     339                 :            : 
     340         [ #  # ]:          0 :         while (count--)
     341                 :          0 :           *dest++ = *data++;
     342                 :            : 
     343                 :            :       } else {
     344                 :            :         /* replicate run */
     345                 :          0 :         row -= count;
     346                 :          0 :         x = *data++;
     347                 :            : 
     348         [ #  # ]:          0 :         while (count--)
     349                 :          0 :           *dest++ = x;
     350                 :            :       }
     351                 :            :     }
     352                 :            :   }
     353                 :            : }
     354                 :            : 
     355                 :            : static void
     356                 :          0 : flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
     357                 :            : {
     358                 :            :   gulong count, packets, lines, start_line;
     359                 :            :   guchar *start_p, x;
     360                 :            : 
     361         [ #  # ]:          0 :   g_return_if_fail (flxdec != NULL);
     362         [ #  # ]:          0 :   g_return_if_fail (flxdec->delta != NULL);
     363                 :            : 
     364                 :            :   /* use last frame for delta */
     365                 :          0 :   memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
     366                 :          0 :       GST_BUFFER_SIZE (flxdec->delta));
     367                 :            : 
     368                 :          0 :   start_line = (data[0] + (data[1] << 8));
     369                 :          0 :   lines = (data[2] + (data[3] << 8));
     370                 :          0 :   data += 4;
     371                 :            : 
     372                 :            :   /* start position of delta */
     373                 :          0 :   dest += (flxdec->hdr.width * start_line);
     374                 :          0 :   start_p = dest;
     375                 :            : 
     376         [ #  # ]:          0 :   while (lines--) {
     377                 :            :     /* packet count */
     378                 :          0 :     packets = *data++;
     379                 :            : 
     380         [ #  # ]:          0 :     while (packets--) {
     381                 :            :       /* skip count */
     382                 :          0 :       dest += *data++;
     383                 :            : 
     384                 :            :       /* RLE count */
     385                 :          0 :       count = *data++;
     386                 :            : 
     387         [ #  # ]:          0 :       if (count > 0x7f) {
     388                 :            :         /* literal run */
     389                 :          0 :         count = 0x100 - count;
     390                 :          0 :         x = *data++;
     391                 :            : 
     392         [ #  # ]:          0 :         while (count--)
     393                 :          0 :           *dest++ = x;
     394                 :            : 
     395                 :            :       } else {
     396                 :            :         /* replicate run */
     397         [ #  # ]:          0 :         while (count--)
     398                 :          0 :           *dest++ = *data++;
     399                 :            :       }
     400                 :            :     }
     401                 :          0 :     start_p += flxdec->hdr.width;
     402                 :          0 :     dest = start_p;
     403                 :            :   }
     404                 :            : }
     405                 :            : 
     406                 :            : static void
     407                 :          0 : flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
     408                 :            : {
     409                 :            :   gulong count, lines, start_l, opcode;
     410                 :            :   guchar *start_p;
     411                 :            : 
     412         [ #  # ]:          0 :   g_return_if_fail (flxdec != NULL);
     413         [ #  # ]:          0 :   g_return_if_fail (flxdec->delta != NULL);
     414                 :            : 
     415                 :            :   /* use last frame for delta */
     416                 :          0 :   memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
     417                 :          0 :       GST_BUFFER_SIZE (flxdec->delta));
     418                 :            : 
     419                 :          0 :   lines = (data[0] + (data[1] << 8));
     420                 :          0 :   data += 2;
     421                 :            : 
     422                 :          0 :   start_p = dest;
     423                 :          0 :   start_l = lines;
     424                 :            : 
     425         [ #  # ]:          0 :   while (lines) {
     426                 :          0 :     dest = start_p + (flxdec->hdr.width * (start_l - lines));
     427                 :            : 
     428                 :            :     /* process opcode(s) */
     429         [ #  # ]:          0 :     while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
     430                 :          0 :       data += 2;
     431         [ #  # ]:          0 :       if ((opcode & 0xc000) == 0xc000) {
     432                 :            :         /* skip count */
     433                 :          0 :         start_l += (0x10000 - opcode);
     434                 :          0 :         dest += flxdec->hdr.width * (0x10000 - opcode);
     435                 :            :       } else {
     436                 :            :         /* last pixel */
     437                 :          0 :         dest += flxdec->hdr.width;
     438                 :          0 :         *dest++ = (opcode & 0xff);
     439                 :            :       }
     440                 :            :     }
     441                 :          0 :     data += 2;
     442                 :            : 
     443                 :            :     /* last opcode is the packet count */
     444         [ #  # ]:          0 :     while (opcode--) {
     445                 :            :       /* skip count */
     446                 :          0 :       dest += *data++;
     447                 :            : 
     448                 :            :       /* RLE count */
     449                 :          0 :       count = *data++;
     450                 :            : 
     451         [ #  # ]:          0 :       if (count > 0x7f) {
     452                 :            :         /* replicate word run */
     453                 :          0 :         count = 0x100 - count;
     454         [ #  # ]:          0 :         while (count--) {
     455                 :          0 :           *dest++ = data[0];
     456                 :          0 :           *dest++ = data[1];
     457                 :            :         }
     458                 :          0 :         data += 2;
     459                 :            :       } else {
     460                 :            :         /* literal word run */
     461         [ #  # ]:          0 :         while (count--) {
     462                 :          0 :           *dest++ = *data++;
     463                 :          0 :           *dest++ = *data++;
     464                 :            :         }
     465                 :            :       }
     466                 :            :     }
     467                 :          0 :     lines--;
     468                 :            :   }
     469                 :            : }
     470                 :            : 
     471                 :            : static GstFlowReturn
     472                 :          0 : gst_flxdec_chain (GstPad * pad, GstBuffer * buf)
     473                 :            : {
     474                 :            :   GstCaps *caps;
     475                 :            :   guint avail;
     476                 :          0 :   GstFlowReturn res = GST_FLOW_OK;
     477                 :            : 
     478                 :            :   GstFlxDec *flxdec;
     479                 :            :   FlxHeader *flxh;
     480                 :            : 
     481         [ #  # ]:          0 :   g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
     482                 :          0 :   flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
     483         [ #  # ]:          0 :   g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR);
     484                 :            : 
     485                 :          0 :   gst_adapter_push (flxdec->adapter, buf);
     486                 :          0 :   avail = gst_adapter_available (flxdec->adapter);
     487                 :            : 
     488         [ #  # ]:          0 :   if (flxdec->state == GST_FLXDEC_READ_HEADER) {
     489         [ #  # ]:          0 :     if (avail >= FlxHeaderSize) {
     490                 :          0 :       const guint8 *data = gst_adapter_peek (flxdec->adapter, FlxHeaderSize);
     491                 :            : 
     492                 :          0 :       memcpy ((gchar *) & flxdec->hdr, data, FlxHeaderSize);
     493                 :            :       FLX_HDR_FIX_ENDIANNESS (&(flxdec->hdr));
     494                 :          0 :       gst_adapter_flush (flxdec->adapter, FlxHeaderSize);
     495                 :            : 
     496                 :          0 :       flxh = &flxdec->hdr;
     497                 :            : 
     498                 :            :       /* check header */
     499 [ #  # ][ #  # ]:          0 :       if (flxh->type != FLX_MAGICHDR_FLI &&
     500         [ #  # ]:          0 :           flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX)
     501                 :          0 :         goto wrong_type;
     502                 :            : 
     503         [ #  # ]:          0 :       GST_LOG ("size      :  %d", flxh->size);
     504         [ #  # ]:          0 :       GST_LOG ("frames    :  %d", flxh->frames);
     505         [ #  # ]:          0 :       GST_LOG ("width     :  %d", flxh->width);
     506         [ #  # ]:          0 :       GST_LOG ("height    :  %d", flxh->height);
     507         [ #  # ]:          0 :       GST_LOG ("depth     :  %d", flxh->depth);
     508         [ #  # ]:          0 :       GST_LOG ("speed     :  %d", flxh->speed);
     509                 :            : 
     510                 :          0 :       flxdec->next_time = 0;
     511                 :            : 
     512         [ #  # ]:          0 :       if (flxh->type == FLX_MAGICHDR_FLI) {
     513                 :          0 :         flxdec->frame_time = JIFFIE * flxh->speed;
     514         [ #  # ]:          0 :       } else if (flxh->speed == 0) {
     515                 :          0 :         flxdec->frame_time = GST_SECOND / 70;
     516                 :            :       } else {
     517                 :          0 :         flxdec->frame_time = flxh->speed * GST_MSECOND;
     518                 :            :       }
     519                 :            : 
     520                 :          0 :       flxdec->duration = flxh->frames * flxdec->frame_time;
     521 [ #  # ][ #  # ]:          0 :       GST_LOG ("duration   :  %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
     522                 :            :           GST_TIME_ARGS (flxdec->duration));
     523                 :            : 
     524                 :          0 :       caps = gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN);
     525                 :          0 :       gst_caps_set_simple (caps,
     526                 :          0 :           "width", G_TYPE_INT, flxh->width,
     527                 :          0 :           "height", G_TYPE_INT, flxh->height,
     528                 :            :           "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND,
     529                 :          0 :           (gint) flxdec->frame_time / 1000, NULL);
     530                 :            : 
     531                 :          0 :       gst_pad_set_caps (flxdec->srcpad, caps);
     532                 :          0 :       gst_caps_unref (caps);
     533                 :            : 
     534         [ #  # ]:          0 :       if (flxh->depth <= 8)
     535                 :          0 :         flxdec->converter =
     536                 :          0 :             flx_colorspace_converter_new (flxh->width, flxh->height);
     537                 :            : 
     538 [ #  # ][ #  # ]:          0 :       if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
     539         [ #  # ]:          0 :         GST_LOG ("(FLC) aspect_dx :  %d", flxh->aspect_dx);
     540         [ #  # ]:          0 :         GST_LOG ("(FLC) aspect_dy :  %d", flxh->aspect_dy);
     541         [ #  # ]:          0 :         GST_LOG ("(FLC) oframe1   :  0x%08x", flxh->oframe1);
     542         [ #  # ]:          0 :         GST_LOG ("(FLC) oframe2   :  0x%08x", flxh->oframe2);
     543                 :            :       }
     544                 :            : 
     545                 :          0 :       flxdec->size = (flxh->width * flxh->height);
     546                 :            : 
     547                 :            :       /* create delta and output frame */
     548                 :          0 :       flxdec->frame = gst_buffer_new ();
     549                 :          0 :       flxdec->delta = gst_buffer_new ();
     550                 :          0 :       GST_BUFFER_DATA (flxdec->frame) = g_malloc (flxdec->size);
     551                 :          0 :       GST_BUFFER_MALLOCDATA (flxdec->frame) = GST_BUFFER_DATA (flxdec->frame);
     552                 :          0 :       GST_BUFFER_SIZE (flxdec->frame) = flxdec->size;
     553                 :          0 :       GST_BUFFER_DATA (flxdec->delta) = g_malloc (flxdec->size);
     554                 :          0 :       GST_BUFFER_MALLOCDATA (flxdec->delta) = GST_BUFFER_DATA (flxdec->delta);
     555                 :          0 :       GST_BUFFER_SIZE (flxdec->delta) = flxdec->size;
     556                 :            : 
     557                 :          0 :       flxdec->state = GST_FLXDEC_PLAYING;
     558                 :            :     }
     559         [ #  # ]:          0 :   } else if (flxdec->state == GST_FLXDEC_PLAYING) {
     560                 :            :     GstBuffer *out;
     561                 :            : 
     562                 :            :     /* while we have enough data in the adapter */
     563         [ #  # ]:          0 :     while (avail >= FlxFrameChunkSize) {
     564                 :            :       FlxFrameChunk flxfh;
     565                 :            :       guchar *chunk;
     566                 :            :       const guint8 *data;
     567                 :            : 
     568                 :          0 :       chunk = NULL;
     569                 :          0 :       data = gst_adapter_peek (flxdec->adapter, FlxFrameChunkSize);
     570                 :          0 :       memcpy (&flxfh, data, FlxFrameChunkSize);
     571                 :            :       FLX_FRAME_CHUNK_FIX_ENDIANNESS (&flxfh);
     572                 :            : 
     573         [ #  # ]:          0 :       switch (flxfh.id) {
     574                 :            :         case FLX_FRAME_TYPE:
     575                 :            :           /* check if we have the complete frame */
     576         [ #  # ]:          0 :           if (avail < flxfh.size)
     577                 :          0 :             goto need_more_data;
     578                 :            : 
     579                 :            :           /* flush header */
     580                 :          0 :           gst_adapter_flush (flxdec->adapter, FlxFrameChunkSize);
     581                 :            : 
     582                 :          0 :           chunk = gst_adapter_take (flxdec->adapter,
     583                 :          0 :               flxfh.size - FlxFrameChunkSize);
     584                 :            :           FLX_FRAME_TYPE_FIX_ENDIANNESS ((FlxFrameType *) chunk);
     585         [ #  # ]:          0 :           if (((FlxFrameType *) chunk)->chunks == 0)
     586                 :          0 :             break;
     587                 :            : 
     588                 :            :           /* create 32 bits output frame */
     589                 :          0 :           res = gst_pad_alloc_buffer_and_set_caps (flxdec->srcpad,
     590                 :            :               GST_BUFFER_OFFSET_NONE,
     591                 :          0 :               flxdec->size * 4, GST_PAD_CAPS (flxdec->srcpad), &out);
     592         [ #  # ]:          0 :           if (res != GST_FLOW_OK)
     593                 :          0 :             break;
     594                 :            : 
     595                 :            :           /* decode chunks */
     596                 :          0 :           flx_decode_chunks (flxdec,
     597                 :          0 :               ((FlxFrameType *) chunk)->chunks,
     598                 :          0 :               chunk + FlxFrameTypeSize, GST_BUFFER_DATA (flxdec->frame));
     599                 :            : 
     600                 :            :           /* save copy of the current frame for possible delta. */
     601                 :          0 :           memcpy (GST_BUFFER_DATA (flxdec->delta),
     602                 :          0 :               GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_SIZE (flxdec->delta));
     603                 :            : 
     604                 :            :           /* convert current frame. */
     605                 :          0 :           flx_colorspace_convert (flxdec->converter,
     606                 :          0 :               GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_DATA (out));
     607                 :            : 
     608                 :          0 :           GST_BUFFER_TIMESTAMP (out) = flxdec->next_time;
     609                 :          0 :           flxdec->next_time += flxdec->frame_time;
     610                 :            : 
     611                 :          0 :           gst_pad_push (flxdec->srcpad, out);
     612                 :          0 :           break;
     613                 :            :       }
     614                 :            : 
     615         [ #  # ]:          0 :       if (chunk)
     616                 :          0 :         g_free (chunk);
     617                 :            : 
     618                 :          0 :       avail = gst_adapter_available (flxdec->adapter);
     619                 :            :     }
     620                 :            :   }
     621                 :            : need_more_data:
     622                 :          0 :   gst_object_unref (flxdec);
     623                 :          0 :   return res;
     624                 :            : 
     625                 :            :   /* ERRORS */
     626                 :            : wrong_type:
     627                 :            :   {
     628 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
         [ #  # ][ #  # ]
     629                 :            :         ("not a flx file (type %x)", flxh->type));
     630                 :          0 :     gst_object_unref (flxdec);
     631                 :          0 :     return GST_FLOW_ERROR;
     632                 :            :   }
     633                 :            : }
     634                 :            : 
     635                 :            : static GstStateChangeReturn
     636                 :         34 : gst_flxdec_change_state (GstElement * element, GstStateChange transition)
     637                 :            : {
     638                 :            :   GstFlxDec *flxdec;
     639                 :            :   GstStateChangeReturn ret;
     640                 :            : 
     641                 :         34 :   flxdec = GST_FLXDEC (element);
     642                 :            : 
     643   [ +  +  +  + ]:         34 :   switch (transition) {
     644                 :            :     case GST_STATE_CHANGE_NULL_TO_READY:
     645                 :          4 :       break;
     646                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
     647                 :          7 :       gst_adapter_clear (flxdec->adapter);
     648                 :          7 :       flxdec->state = GST_FLXDEC_READ_HEADER;
     649                 :          7 :       break;
     650                 :            :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     651                 :          6 :       break;
     652                 :            :     default:
     653                 :         17 :       break;
     654                 :            :   }
     655                 :            : 
     656                 :         34 :   ret = parent_class->change_state (element, transition);
     657                 :            : 
     658   [ +  +  +  + ]:         34 :   switch (transition) {
     659                 :            :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     660                 :          6 :       break;
     661                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
     662         [ -  + ]:          7 :       if (flxdec->frame) {
     663                 :          0 :         gst_buffer_unref (flxdec->frame);
     664                 :          0 :         flxdec->frame = NULL;
     665                 :            :       }
     666         [ -  + ]:          7 :       if (flxdec->delta) {
     667                 :          0 :         gst_buffer_unref (flxdec->delta);
     668                 :          0 :         flxdec->delta = NULL;
     669                 :            :       }
     670                 :          7 :       break;
     671                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
     672                 :          4 :       break;
     673                 :            :     default:
     674                 :         17 :       break;
     675                 :            :   }
     676                 :         34 :   return ret;
     677                 :            : }
     678                 :            : 
     679                 :            : static gboolean
     680                 :          4 : plugin_init (GstPlugin * plugin)
     681                 :            : {
     682                 :          4 :   return gst_element_register (plugin, "flxdec",
     683                 :            :       GST_RANK_PRIMARY, GST_TYPE_FLXDEC);
     684                 :            : }
     685                 :            : 
     686                 :            : GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     687                 :            :     GST_VERSION_MINOR,
     688                 :            :     "flxdec",
     689                 :            :     "FLC/FLI/FLX video decoder",
     690                 :            :     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

Generated by: LCOV version 1.9