Blame gst/rtp/gstrtpjpegdepay.c

Packit 1f69a5
/* GStreamer
Packit 1f69a5
 * Copyright (C) <2008> Wim Taymans <wim.taymans@gmail.com>
Packit 1f69a5
 *
Packit 1f69a5
 * This library is free software; you can redistribute it and/or
Packit 1f69a5
 * modify it under the terms of the GNU Library General Public
Packit 1f69a5
 * License as published by the Free Software Foundation; either
Packit 1f69a5
 * version 2 of the License, or (at your option) any later version.
Packit 1f69a5
 *
Packit 1f69a5
 * This library is distributed in the hope that it will be useful,
Packit 1f69a5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1f69a5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1f69a5
 * Library General Public License for more details.
Packit 1f69a5
 *
Packit 1f69a5
 * You should have received a copy of the GNU Library General Public
Packit 1f69a5
 * License along with this library; if not, write to the
Packit 1f69a5
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 1f69a5
 * Boston, MA 02110-1301, USA.
Packit 1f69a5
 */
Packit 1f69a5
Packit 1f69a5
#ifdef HAVE_CONFIG_H
Packit 1f69a5
#  include "config.h"
Packit 1f69a5
#endif
Packit 1f69a5
Packit 1f69a5
#include <gst/rtp/gstrtpbuffer.h>
Packit 1f69a5
#include <gst/video/video.h>
Packit 1f69a5
Packit 1f69a5
#include <math.h>
Packit 1f69a5
#include <stdio.h>
Packit 1f69a5
#include <stdlib.h>
Packit 1f69a5
#include <string.h>
Packit 1f69a5
#include "gstrtpjpegdepay.h"
Packit 1f69a5
#include "gstrtputils.h"
Packit 1f69a5
Packit 1f69a5
GST_DEBUG_CATEGORY_STATIC (rtpjpegdepay_debug);
Packit 1f69a5
#define GST_CAT_DEFAULT (rtpjpegdepay_debug)
Packit 1f69a5
Packit 1f69a5
static GstStaticPadTemplate gst_rtp_jpeg_depay_src_template =
Packit 1f69a5
GST_STATIC_PAD_TEMPLATE ("src",
Packit 1f69a5
    GST_PAD_SRC,
Packit 1f69a5
    GST_PAD_ALWAYS,
Packit 1f69a5
    GST_STATIC_CAPS ("image/jpeg")
Packit 1f69a5
    );
Packit 1f69a5
Packit 1f69a5
static GstStaticPadTemplate gst_rtp_jpeg_depay_sink_template =
Packit 1f69a5
    GST_STATIC_PAD_TEMPLATE ("sink",
Packit 1f69a5
    GST_PAD_SINK,
Packit 1f69a5
    GST_PAD_ALWAYS,
Packit 1f69a5
    GST_STATIC_CAPS ("application/x-rtp, "
Packit 1f69a5
        "media = (string) \"video\", "
Packit 1f69a5
        "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG\"; "
Packit 1f69a5
        /* optional SDP attributes */
Packit 1f69a5
        /*
Packit 1f69a5
         * "a-framerate = (string) 0.00, "
Packit 1f69a5
         * "x-framerate = (string) 0.00, "
Packit 1f69a5
         * "x-dimensions = (string) \"1234,1234\", "
Packit 1f69a5
         */
Packit 1f69a5
        "application/x-rtp, "
Packit 1f69a5
        "media = (string) \"video\", "
Packit 1f69a5
        "payload = (int) " GST_RTP_PAYLOAD_JPEG_STRING ", "
Packit 1f69a5
        "clock-rate = (int) 90000"
Packit 1f69a5
        /* optional SDP attributes */
Packit 1f69a5
        /*
Packit 1f69a5
         * "a-framerate = (string) 0.00, "
Packit 1f69a5
         * "x-framerate = (string) 0.00, "
Packit 1f69a5
         * "x-dimensions = (string) \"1234,1234\""
Packit 1f69a5
         */
Packit 1f69a5
    )
Packit 1f69a5
    );
Packit 1f69a5
Packit 1f69a5
#define gst_rtp_jpeg_depay_parent_class parent_class
Packit 1f69a5
G_DEFINE_TYPE (GstRtpJPEGDepay, gst_rtp_jpeg_depay,
Packit 1f69a5
    GST_TYPE_RTP_BASE_DEPAYLOAD);
Packit 1f69a5
Packit 1f69a5
static void gst_rtp_jpeg_depay_finalize (GObject * object);
Packit 1f69a5
Packit 1f69a5
static GstStateChangeReturn gst_rtp_jpeg_depay_change_state (GstElement *
Packit 1f69a5
    element, GstStateChange transition);
Packit 1f69a5
Packit 1f69a5
static gboolean gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload,
Packit 1f69a5
    GstCaps * caps);
Packit 1f69a5
static GstBuffer *gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload,
Packit 1f69a5
    GstRTPBuffer * rtp);
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass)
Packit 1f69a5
{
Packit 1f69a5
  GObjectClass *gobject_class;
Packit 1f69a5
  GstElementClass *gstelement_class;
Packit 1f69a5
  GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
Packit 1f69a5
Packit 1f69a5
  gobject_class = (GObjectClass *) klass;
Packit 1f69a5
  gstelement_class = (GstElementClass *) klass;
Packit 1f69a5
  gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
Packit 1f69a5
Packit 1f69a5
  gobject_class->finalize = gst_rtp_jpeg_depay_finalize;
Packit 1f69a5
Packit 1f69a5
  gst_element_class_add_static_pad_template (gstelement_class,
Packit 1f69a5
      &gst_rtp_jpeg_depay_src_template);
Packit 1f69a5
  gst_element_class_add_static_pad_template (gstelement_class,
Packit 1f69a5
      &gst_rtp_jpeg_depay_sink_template);
Packit 1f69a5
Packit 1f69a5
  gst_element_class_set_static_metadata (gstelement_class,
Packit 1f69a5
      "RTP JPEG depayloader", "Codec/Depayloader/Network/RTP",
Packit 1f69a5
      "Extracts JPEG video from RTP packets (RFC 2435)",
Packit 1f69a5
      "Wim Taymans <wim.taymans@gmail.com>");
Packit 1f69a5
Packit 1f69a5
  gstelement_class->change_state = gst_rtp_jpeg_depay_change_state;
Packit 1f69a5
Packit 1f69a5
  gstrtpbasedepayload_class->set_caps = gst_rtp_jpeg_depay_setcaps;
Packit 1f69a5
  gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_jpeg_depay_process;
Packit 1f69a5
Packit 1f69a5
  GST_DEBUG_CATEGORY_INIT (rtpjpegdepay_debug, "rtpjpegdepay", 0,
Packit 1f69a5
      "JPEG Video RTP Depayloader");
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_rtp_jpeg_depay_init (GstRtpJPEGDepay * rtpjpegdepay)
Packit 1f69a5
{
Packit 1f69a5
  rtpjpegdepay->adapter = gst_adapter_new ();
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_rtp_jpeg_depay_reset (GstRtpJPEGDepay * depay)
Packit 1f69a5
{
Packit 1f69a5
  gint i;
Packit 1f69a5
Packit 1f69a5
  depay->width = 0;
Packit 1f69a5
  depay->height = 0;
Packit 1f69a5
  depay->media_width = 0;
Packit 1f69a5
  depay->media_height = 0;
Packit 1f69a5
  depay->frate_num = 0;
Packit 1f69a5
  depay->frate_denom = 1;
Packit 1f69a5
  depay->discont = TRUE;
Packit 1f69a5
Packit 1f69a5
  for (i = 0; i < 255; i++) {
Packit 1f69a5
    g_free (depay->qtables[i]);
Packit 1f69a5
    depay->qtables[i] = NULL;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  gst_adapter_clear (depay->adapter);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_rtp_jpeg_depay_finalize (GObject * object)
Packit 1f69a5
{
Packit 1f69a5
  GstRtpJPEGDepay *rtpjpegdepay;
Packit 1f69a5
Packit 1f69a5
  rtpjpegdepay = GST_RTP_JPEG_DEPAY (object);
Packit 1f69a5
Packit 1f69a5
  gst_rtp_jpeg_depay_reset (rtpjpegdepay);
Packit 1f69a5
Packit 1f69a5
  g_object_unref (rtpjpegdepay->adapter);
Packit 1f69a5
  rtpjpegdepay->adapter = NULL;
Packit 1f69a5
Packit 1f69a5
  G_OBJECT_CLASS (parent_class)->finalize (object);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static const int zigzag[] = {
Packit 1f69a5
  0, 1, 8, 16, 9, 2, 3, 10,
Packit 1f69a5
  17, 24, 32, 25, 18, 11, 4, 5,
Packit 1f69a5
  12, 19, 26, 33, 40, 48, 41, 34,
Packit 1f69a5
  27, 20, 13, 6, 7, 14, 21, 28,
Packit 1f69a5
  35, 42, 49, 56, 57, 50, 43, 36,
Packit 1f69a5
  29, 22, 15, 23, 30, 37, 44, 51,
Packit 1f69a5
  58, 59, 52, 45, 38, 31, 39, 46,
Packit 1f69a5
  53, 60, 61, 54, 47, 55, 62, 63
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
/*
Packit 1f69a5
 * Table K.1 from JPEG spec.
Packit 1f69a5
 */
Packit 1f69a5
static const int jpeg_luma_quantizer[64] = {
Packit 1f69a5
  16, 11, 10, 16, 24, 40, 51, 61,
Packit 1f69a5
  12, 12, 14, 19, 26, 58, 60, 55,
Packit 1f69a5
  14, 13, 16, 24, 40, 57, 69, 56,
Packit 1f69a5
  14, 17, 22, 29, 51, 87, 80, 62,
Packit 1f69a5
  18, 22, 37, 56, 68, 109, 103, 77,
Packit 1f69a5
  24, 35, 55, 64, 81, 104, 113, 92,
Packit 1f69a5
  49, 64, 78, 87, 103, 121, 120, 101,
Packit 1f69a5
  72, 92, 95, 98, 112, 100, 103, 99
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
/*
Packit 1f69a5
 * Table K.2 from JPEG spec.
Packit 1f69a5
 */
Packit 1f69a5
static const int jpeg_chroma_quantizer[64] = {
Packit 1f69a5
  17, 18, 24, 47, 99, 99, 99, 99,
Packit 1f69a5
  18, 21, 26, 66, 99, 99, 99, 99,
Packit 1f69a5
  24, 26, 56, 99, 99, 99, 99, 99,
Packit 1f69a5
  47, 66, 99, 99, 99, 99, 99, 99,
Packit 1f69a5
  99, 99, 99, 99, 99, 99, 99, 99,
Packit 1f69a5
  99, 99, 99, 99, 99, 99, 99, 99,
Packit 1f69a5
  99, 99, 99, 99, 99, 99, 99, 99,
Packit 1f69a5
  99, 99, 99, 99, 99, 99, 99, 99
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
/* Call MakeTables with the Q factor and a guint8[128] return array
Packit 1f69a5
 */
Packit 1f69a5
static void
Packit 1f69a5
MakeTables (GstRtpJPEGDepay * rtpjpegdepay, gint Q, guint8 qtable[128])
Packit 1f69a5
{
Packit 1f69a5
  gint i;
Packit 1f69a5
  guint factor;
Packit 1f69a5
Packit 1f69a5
  factor = CLAMP (Q, 1, 99);
Packit 1f69a5
Packit 1f69a5
  if (Q < 50)
Packit 1f69a5
    Q = 5000 / factor;
Packit 1f69a5
  else
Packit 1f69a5
    Q = 200 - factor * 2;
Packit 1f69a5
Packit 1f69a5
  for (i = 0; i < 64; i++) {
Packit 1f69a5
    gint lq = (jpeg_luma_quantizer[zigzag[i]] * Q + 50) / 100;
Packit 1f69a5
    gint cq = (jpeg_chroma_quantizer[zigzag[i]] * Q + 50) / 100;
Packit 1f69a5
Packit 1f69a5
    /* Limit the quantizers to 1 <= q <= 255 */
Packit 1f69a5
    qtable[i] = CLAMP (lq, 1, 255);
Packit 1f69a5
    qtable[i + 64] = CLAMP (cq, 1, 255);
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static const guint8 lum_dc_codelens[] = {
Packit 1f69a5
  0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 lum_dc_symbols[] = {
Packit 1f69a5
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 lum_ac_codelens[] = {
Packit 1f69a5
  0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 lum_ac_symbols[] = {
Packit 1f69a5
  0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
Packit 1f69a5
  0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
Packit 1f69a5
  0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
Packit 1f69a5
  0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
Packit 1f69a5
  0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
Packit 1f69a5
  0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
Packit 1f69a5
  0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
Packit 1f69a5
  0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
Packit 1f69a5
  0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
Packit 1f69a5
  0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
Packit 1f69a5
  0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
Packit 1f69a5
  0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
Packit 1f69a5
  0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
Packit 1f69a5
  0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
Packit 1f69a5
  0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
Packit 1f69a5
  0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
Packit 1f69a5
  0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
Packit 1f69a5
  0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
Packit 1f69a5
  0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
Packit 1f69a5
  0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
Packit 1f69a5
  0xf9, 0xfa
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 chm_dc_codelens[] = {
Packit 1f69a5
  0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 chm_dc_symbols[] = {
Packit 1f69a5
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 chm_ac_codelens[] = {
Packit 1f69a5
  0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static const guint8 chm_ac_symbols[] = {
Packit 1f69a5
  0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
Packit 1f69a5
  0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
Packit 1f69a5
  0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
Packit 1f69a5
  0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
Packit 1f69a5
  0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
Packit 1f69a5
  0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
Packit 1f69a5
  0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
Packit 1f69a5
  0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
Packit 1f69a5
  0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
Packit 1f69a5
  0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
Packit 1f69a5
  0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
Packit 1f69a5
  0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
Packit 1f69a5
  0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
Packit 1f69a5
  0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
Packit 1f69a5
  0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
Packit 1f69a5
  0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
Packit 1f69a5
  0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
Packit 1f69a5
  0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
Packit 1f69a5
  0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
Packit 1f69a5
  0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
Packit 1f69a5
  0xf9, 0xfa
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static guint8 *
Packit 1f69a5
MakeQuantHeader (guint8 * p, guint8 * qt, gint size, gint tableNo)
Packit 1f69a5
{
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xdb;                  /* DQT */
Packit 1f69a5
  *p++ = 0;                     /* length msb */
Packit 1f69a5
  *p++ = size + 3;              /* length lsb */
Packit 1f69a5
  *p++ = tableNo;
Packit 1f69a5
  memcpy (p, qt, size);
Packit 1f69a5
Packit 1f69a5
  return (p + size);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static guint8 *
Packit 1f69a5
MakeHuffmanHeader (guint8 * p, const guint8 * codelens, int ncodes,
Packit 1f69a5
    const guint8 * symbols, int nsymbols, int tableNo, int tableClass)
Packit 1f69a5
{
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xc4;                  /* DHT */
Packit 1f69a5
  *p++ = 0;                     /* length msb */
Packit 1f69a5
  *p++ = 3 + ncodes + nsymbols; /* length lsb */
Packit 1f69a5
  *p++ = (tableClass << 4) | tableNo;
Packit 1f69a5
  memcpy (p, codelens, ncodes);
Packit 1f69a5
  p += ncodes;
Packit 1f69a5
  memcpy (p, symbols, nsymbols);
Packit 1f69a5
  p += nsymbols;
Packit 1f69a5
Packit 1f69a5
  return (p);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static guint8 *
Packit 1f69a5
MakeDRIHeader (guint8 * p, guint16 dri)
Packit 1f69a5
{
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xdd;                  /* DRI */
Packit 1f69a5
  *p++ = 0x0;                   /* length msb */
Packit 1f69a5
  *p++ = 4;                     /* length lsb */
Packit 1f69a5
  *p++ = dri >> 8;              /* dri msb */
Packit 1f69a5
  *p++ = dri & 0xff;            /* dri lsb */
Packit 1f69a5
Packit 1f69a5
  return (p);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
/*
Packit 1f69a5
 *  Arguments:
Packit 1f69a5
 *    type, width, height: as supplied in RTP/JPEG header
Packit 1f69a5
 *    qt: quantization tables as either derived from
Packit 1f69a5
 *        the Q field using MakeTables() or as specified
Packit 1f69a5
 *        in section 4.2.
Packit 1f69a5
 *    dri: restart interval in MCUs, or 0 if no restarts.
Packit 1f69a5
 *
Packit 1f69a5
 *    p: pointer to return area
Packit 1f69a5
 *
Packit 1f69a5
 *  Return value:
Packit 1f69a5
 *    The length of the generated headers.
Packit 1f69a5
 *
Packit 1f69a5
 *    Generate a frame and scan headers that can be prepended to the
Packit 1f69a5
 *    RTP/JPEG data payload to produce a JPEG compressed image in
Packit 1f69a5
 *    interchange format (except for possible trailing garbage and
Packit 1f69a5
 *    absence of an EOI marker to terminate the scan).
Packit 1f69a5
 */
Packit 1f69a5
static guint
Packit 1f69a5
MakeHeaders (guint8 * p, int type, int width, int height, guint8 * qt,
Packit 1f69a5
    guint precision, guint16 dri)
Packit 1f69a5
{
Packit 1f69a5
  guint8 *start = p;
Packit 1f69a5
  gint size;
Packit 1f69a5
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xd8;                  /* SOI */
Packit 1f69a5
Packit 1f69a5
  size = ((precision & 1) ? 128 : 64);
Packit 1f69a5
  p = MakeQuantHeader (p, qt, size, 0);
Packit 1f69a5
  qt += size;
Packit 1f69a5
Packit 1f69a5
  size = ((precision & 2) ? 128 : 64);
Packit 1f69a5
  p = MakeQuantHeader (p, qt, size, 1);
Packit 1f69a5
  qt += size;
Packit 1f69a5
Packit 1f69a5
  if (dri != 0)
Packit 1f69a5
    p = MakeDRIHeader (p, dri);
Packit 1f69a5
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xc0;                  /* SOF */
Packit 1f69a5
  *p++ = 0;                     /* length msb */
Packit 1f69a5
  *p++ = 17;                    /* length lsb */
Packit 1f69a5
  *p++ = 8;                     /* 8-bit precision */
Packit 1f69a5
  *p++ = height >> 8;           /* height msb */
Packit 1f69a5
  *p++ = height;                /* height lsb */
Packit 1f69a5
  *p++ = width >> 8;            /* width msb */
Packit 1f69a5
  *p++ = width;                 /* width lsb */
Packit 1f69a5
  *p++ = 3;                     /* number of components */
Packit 1f69a5
  *p++ = 0;                     /* comp 0 */
Packit 1f69a5
  if ((type & 0x3f) == 0)
Packit 1f69a5
    *p++ = 0x21;                /* hsamp = 2, vsamp = 1 */
Packit 1f69a5
  else
Packit 1f69a5
    *p++ = 0x22;                /* hsamp = 2, vsamp = 2 */
Packit 1f69a5
  *p++ = 0;                     /* quant table 0 */
Packit 1f69a5
  *p++ = 1;                     /* comp 1 */
Packit 1f69a5
  *p++ = 0x11;                  /* hsamp = 1, vsamp = 1 */
Packit 1f69a5
  *p++ = 1;                     /* quant table 1 */
Packit 1f69a5
  *p++ = 2;                     /* comp 2 */
Packit 1f69a5
  *p++ = 0x11;                  /* hsamp = 1, vsamp = 1 */
Packit 1f69a5
  *p++ = 1;                     /* quant table 1 */
Packit 1f69a5
Packit 1f69a5
  p = MakeHuffmanHeader (p, lum_dc_codelens,
Packit 1f69a5
      sizeof (lum_dc_codelens), lum_dc_symbols, sizeof (lum_dc_symbols), 0, 0);
Packit 1f69a5
  p = MakeHuffmanHeader (p, lum_ac_codelens,
Packit 1f69a5
      sizeof (lum_ac_codelens), lum_ac_symbols, sizeof (lum_ac_symbols), 0, 1);
Packit 1f69a5
  p = MakeHuffmanHeader (p, chm_dc_codelens,
Packit 1f69a5
      sizeof (chm_dc_codelens), chm_dc_symbols, sizeof (chm_dc_symbols), 1, 0);
Packit 1f69a5
  p = MakeHuffmanHeader (p, chm_ac_codelens,
Packit 1f69a5
      sizeof (chm_ac_codelens), chm_ac_symbols, sizeof (chm_ac_symbols), 1, 1);
Packit 1f69a5
Packit 1f69a5
  *p++ = 0xff;
Packit 1f69a5
  *p++ = 0xda;                  /* SOS */
Packit 1f69a5
  *p++ = 0;                     /* length msb */
Packit 1f69a5
  *p++ = 12;                    /* length lsb */
Packit 1f69a5
  *p++ = 3;                     /* 3 components */
Packit 1f69a5
  *p++ = 0;                     /* comp 0 */
Packit 1f69a5
  *p++ = 0;                     /* huffman table 0 */
Packit 1f69a5
  *p++ = 1;                     /* comp 1 */
Packit 1f69a5
  *p++ = 0x11;                  /* huffman table 1 */
Packit 1f69a5
  *p++ = 2;                     /* comp 2 */
Packit 1f69a5
  *p++ = 0x11;                  /* huffman table 1 */
Packit 1f69a5
  *p++ = 0;                     /* first DCT coeff */
Packit 1f69a5
  *p++ = 63;                    /* last DCT coeff */
Packit 1f69a5
  *p++ = 0;                     /* sucessive approx. */
Packit 1f69a5
Packit 1f69a5
  return (p - start);
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
Packit 1f69a5
{
Packit 1f69a5
  GstRtpJPEGDepay *rtpjpegdepay;
Packit 1f69a5
  GstStructure *structure;
Packit 1f69a5
  gint clock_rate;
Packit 1f69a5
  const gchar *media_attr;
Packit 1f69a5
Packit 1f69a5
  rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
Packit 1f69a5
Packit 1f69a5
  structure = gst_caps_get_structure (caps, 0);
Packit 1f69a5
  GST_DEBUG_OBJECT (rtpjpegdepay, "Caps set: %" GST_PTR_FORMAT, caps);
Packit 1f69a5
Packit 1f69a5
  if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
Packit 1f69a5
    clock_rate = 90000;
Packit 1f69a5
  depayload->clock_rate = clock_rate;
Packit 1f69a5
Packit 1f69a5
  /* reset defaults */
Packit 1f69a5
  rtpjpegdepay->width = 0;
Packit 1f69a5
  rtpjpegdepay->height = 0;
Packit 1f69a5
  rtpjpegdepay->media_width = 0;
Packit 1f69a5
  rtpjpegdepay->media_height = 0;
Packit 1f69a5
  rtpjpegdepay->frate_num = 0;
Packit 1f69a5
  rtpjpegdepay->frate_denom = 1;
Packit 1f69a5
Packit 1f69a5
  /* check for optional SDP attributes */
Packit 1f69a5
  if ((media_attr = gst_structure_get_string (structure, "x-dimensions"))) {
Packit 1f69a5
    gint w, h;
Packit 1f69a5
Packit 1f69a5
    if (sscanf (media_attr, "%d,%d", &w, &h) == 2) {
Packit 1f69a5
      rtpjpegdepay->media_width = w;
Packit 1f69a5
      rtpjpegdepay->media_height = h;
Packit 1f69a5
    }
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  /* try to get a framerate */
Packit 1f69a5
  media_attr = gst_structure_get_string (structure, "a-framerate");
Packit 1f69a5
  if (!media_attr)
Packit 1f69a5
    media_attr = gst_structure_get_string (structure, "x-framerate");
Packit 1f69a5
Packit 1f69a5
  if (media_attr) {
Packit 1f69a5
    GValue src = { 0 };
Packit 1f69a5
    GValue dest = { 0 };
Packit 1f69a5
    gchar *s;
Packit 1f69a5
Packit 1f69a5
    /* canonicalise floating point string so we can handle framerate strings
Packit 1f69a5
     * in the form "24.930" or "24,930" irrespective of the current locale */
Packit 1f69a5
    s = g_strdup (media_attr);
Packit 1f69a5
    g_strdelimit (s, ",", '.');
Packit 1f69a5
Packit 1f69a5
    /* convert the float to a fraction */
Packit 1f69a5
    g_value_init (&src, G_TYPE_DOUBLE);
Packit 1f69a5
    g_value_set_double (&src, g_ascii_strtod (s, NULL));
Packit 1f69a5
    g_value_init (&dest, GST_TYPE_FRACTION);
Packit 1f69a5
    g_value_transform (&src, &dest);
Packit 1f69a5
Packit 1f69a5
    rtpjpegdepay->frate_num = gst_value_get_fraction_numerator (&dest);
Packit 1f69a5
    rtpjpegdepay->frate_denom = gst_value_get_fraction_denominator (&dest);
Packit 1f69a5
Packit 1f69a5
    g_free (s);
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static GstBuffer *
Packit 1f69a5
gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
Packit 1f69a5
{
Packit 1f69a5
  GstRtpJPEGDepay *rtpjpegdepay;
Packit 1f69a5
  GstBuffer *outbuf;
Packit 1f69a5
  gint payload_len, header_len;
Packit 1f69a5
  guint8 *payload;
Packit 1f69a5
  guint frag_offset;
Packit 1f69a5
  gint Q;
Packit 1f69a5
  guint type, width, height;
Packit 1f69a5
  guint16 dri, precision, length;
Packit 1f69a5
  guint8 *qtable;
Packit 1f69a5
Packit 1f69a5
  rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
Packit 1f69a5
Packit 1f69a5
  if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
Packit 1f69a5
    GST_DEBUG_OBJECT (depayload, "DISCONT, reset adapter");
Packit 1f69a5
    gst_adapter_clear (rtpjpegdepay->adapter);
Packit 1f69a5
    rtpjpegdepay->discont = TRUE;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  payload_len = gst_rtp_buffer_get_payload_len (rtp);
Packit 1f69a5
Packit 1f69a5
  if (payload_len < 8)
Packit 1f69a5
    goto empty_packet;
Packit 1f69a5
Packit 1f69a5
  payload = gst_rtp_buffer_get_payload (rtp);
Packit 1f69a5
  header_len = 0;
Packit 1f69a5
Packit 1f69a5
  /*  0                   1                   2                   3
Packit 1f69a5
   *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Packit 1f69a5
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
   * | Type-specific |              Fragment Offset                  |
Packit 1f69a5
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
   * |      Type     |       Q       |     Width     |     Height    |
Packit 1f69a5
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
   */
Packit 1f69a5
  frag_offset = (payload[1] << 16) | (payload[2] << 8) | payload[3];
Packit 1f69a5
  type = payload[4];
Packit 1f69a5
  Q = payload[5];
Packit 1f69a5
  width = payload[6] * 8;
Packit 1f69a5
  height = payload[7] * 8;
Packit 1f69a5
Packit 1f69a5
  /* saw a packet with fragment offset > 0 and we don't already have data queued
Packit 1f69a5
   * up (most importantly, we don't have a header for this data) -- drop it
Packit 1f69a5
   * XXX: maybe we can check if the jpeg is progressive and salvage the data?
Packit 1f69a5
   * XXX: not implemented yet because jpegenc can't create progressive jpegs */
Packit 1f69a5
  if (frag_offset > 0 && gst_adapter_available (rtpjpegdepay->adapter) == 0)
Packit 1f69a5
    goto no_header_packet;
Packit 1f69a5
Packit 1f69a5
  /* allow frame dimensions > 2040, passed in SDP session or media attributes
Packit 1f69a5
   * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
Packit 1f69a5
  if (!width)
Packit 1f69a5
    width = rtpjpegdepay->media_width;
Packit 1f69a5
Packit 1f69a5
  if (!height)
Packit 1f69a5
    height = rtpjpegdepay->media_height;
Packit 1f69a5
Packit 1f69a5
  if (width == 0 || height == 0)
Packit 1f69a5
    goto invalid_dimension;
Packit 1f69a5
Packit 1f69a5
  GST_DEBUG_OBJECT (rtpjpegdepay, "frag %u, type %u, Q %d, width %u, height %u",
Packit 1f69a5
      frag_offset, type, Q, width, height);
Packit 1f69a5
Packit 1f69a5
  header_len += 8;
Packit 1f69a5
  payload += 8;
Packit 1f69a5
  payload_len -= 8;
Packit 1f69a5
Packit 1f69a5
  dri = 0;
Packit 1f69a5
  if (type > 63) {
Packit 1f69a5
    if (payload_len < 4)
Packit 1f69a5
      goto empty_packet;
Packit 1f69a5
Packit 1f69a5
    /*  0                   1                   2                   3
Packit 1f69a5
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Packit 1f69a5
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
     * |       Restart Interval        |F|L|       Restart Count       |
Packit 1f69a5
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
     */
Packit 1f69a5
    dri = (payload[0] << 8) | payload[1];
Packit 1f69a5
Packit 1f69a5
    GST_DEBUG_OBJECT (rtpjpegdepay, "DRI %" G_GUINT16_FORMAT, dri);
Packit 1f69a5
Packit 1f69a5
    payload += 4;
Packit 1f69a5
    header_len += 4;
Packit 1f69a5
    payload_len -= 4;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  if (Q >= 128 && frag_offset == 0) {
Packit 1f69a5
    if (payload_len < 4)
Packit 1f69a5
      goto empty_packet;
Packit 1f69a5
Packit 1f69a5
    /*  0                   1                   2                   3
Packit 1f69a5
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Packit 1f69a5
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
     * |      MBZ      |   Precision   |             Length            |
Packit 1f69a5
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
     * |                    Quantization Table Data                    |
Packit 1f69a5
     * |                              ...                              |
Packit 1f69a5
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Packit 1f69a5
     */
Packit 1f69a5
    precision = payload[1];
Packit 1f69a5
    length = (payload[2] << 8) | payload[3];
Packit 1f69a5
Packit 1f69a5
    GST_DEBUG_OBJECT (rtpjpegdepay, "precision %04x, length %" G_GUINT16_FORMAT,
Packit 1f69a5
        precision, length);
Packit 1f69a5
Packit 1f69a5
    if (Q == 255 && length == 0)
Packit 1f69a5
      goto empty_packet;
Packit 1f69a5
Packit 1f69a5
    payload += 4;
Packit 1f69a5
    header_len += 4;
Packit 1f69a5
    payload_len -= 4;
Packit 1f69a5
Packit 1f69a5
    if (length > payload_len)
Packit 1f69a5
      goto empty_packet;
Packit 1f69a5
Packit 1f69a5
    if (length > 0)
Packit 1f69a5
      qtable = payload;
Packit 1f69a5
    else
Packit 1f69a5
      qtable = rtpjpegdepay->qtables[Q];
Packit 1f69a5
Packit 1f69a5
    payload += length;
Packit 1f69a5
    header_len += length;
Packit 1f69a5
    payload_len -= length;
Packit 1f69a5
  } else {
Packit 1f69a5
    length = 0;
Packit 1f69a5
    qtable = NULL;
Packit 1f69a5
    precision = 0;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  if (frag_offset == 0) {
Packit 1f69a5
    GstMapInfo map;
Packit 1f69a5
    guint size;
Packit 1f69a5
Packit 1f69a5
    if (rtpjpegdepay->width != width || rtpjpegdepay->height != height) {
Packit 1f69a5
      GstCaps *outcaps;
Packit 1f69a5
Packit 1f69a5
      outcaps =
Packit 1f69a5
          gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
Packit 1f69a5
          rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
Packit 1f69a5
          G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
Packit 1f69a5
      gst_pad_set_caps (depayload->srcpad, outcaps);
Packit 1f69a5
      gst_caps_unref (outcaps);
Packit 1f69a5
Packit 1f69a5
      rtpjpegdepay->width = width;
Packit 1f69a5
      rtpjpegdepay->height = height;
Packit 1f69a5
    }
Packit 1f69a5
Packit 1f69a5
    GST_LOG_OBJECT (rtpjpegdepay, "first packet, length %" G_GUINT16_FORMAT,
Packit 1f69a5
        length);
Packit 1f69a5
Packit 1f69a5
    /* first packet */
Packit 1f69a5
    if (length == 0) {
Packit 1f69a5
      if (Q < 128) {
Packit 1f69a5
        /* no quant table, see if we have one cached */
Packit 1f69a5
        qtable = rtpjpegdepay->qtables[Q];
Packit 1f69a5
        if (!qtable) {
Packit 1f69a5
          GST_DEBUG_OBJECT (rtpjpegdepay, "making Q %d table", Q);
Packit 1f69a5
          /* make and cache the table */
Packit 1f69a5
          qtable = g_new (guint8, 128);
Packit 1f69a5
          MakeTables (rtpjpegdepay, Q, qtable);
Packit 1f69a5
          rtpjpegdepay->qtables[Q] = qtable;
Packit 1f69a5
        } else {
Packit 1f69a5
          GST_DEBUG_OBJECT (rtpjpegdepay, "using cached table for Q %d", Q);
Packit 1f69a5
        }
Packit 1f69a5
        /* all 8 bit quantizers */
Packit 1f69a5
        precision = 0;
Packit 1f69a5
      } else {
Packit 1f69a5
        if (!qtable)
Packit 1f69a5
          goto no_qtable;
Packit 1f69a5
      }
Packit 1f69a5
    }
Packit 1f69a5
Packit 1f69a5
    /* I think we can get here with a NULL qtable, so make sure we don't
Packit 1f69a5
       go dereferencing it in MakeHeaders if we do */
Packit 1f69a5
    if (!qtable)
Packit 1f69a5
      goto no_qtable;
Packit 1f69a5
Packit 1f69a5
    /* max header length, should be big enough */
Packit 1f69a5
    outbuf = gst_buffer_new_and_alloc (1000);
Packit 1f69a5
    gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
Packit 1f69a5
    size = MakeHeaders (map.data, type, width, height, qtable, precision, dri);
Packit 1f69a5
    gst_buffer_unmap (outbuf, &map);
Packit 1f69a5
    gst_buffer_resize (outbuf, 0, size);
Packit 1f69a5
Packit 1f69a5
    GST_DEBUG_OBJECT (rtpjpegdepay, "pushing %u bytes of header", size);
Packit 1f69a5
Packit 1f69a5
    gst_adapter_push (rtpjpegdepay->adapter, outbuf);
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  /* take JPEG data, push in the adapter */
Packit 1f69a5
  GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
Packit 1f69a5
  outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, -1);
Packit 1f69a5
  gst_adapter_push (rtpjpegdepay->adapter, outbuf);
Packit 1f69a5
  outbuf = NULL;
Packit 1f69a5
Packit 1f69a5
  if (gst_rtp_buffer_get_marker (rtp)) {
Packit 1f69a5
    guint avail;
Packit 1f69a5
    guint8 end[2];
Packit 1f69a5
    GstMapInfo map;
Packit 1f69a5
Packit 1f69a5
    /* last buffer take all data out of the adapter */
Packit 1f69a5
    avail = gst_adapter_available (rtpjpegdepay->adapter);
Packit 1f69a5
    GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");
Packit 1f69a5
Packit 1f69a5
    if (avail < 2)
Packit 1f69a5
      goto invalid_packet;
Packit 1f69a5
Packit 1f69a5
    /* take the last bytes of the jpeg data to see if there is an EOI
Packit 1f69a5
     * marker */
Packit 1f69a5
    gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);
Packit 1f69a5
Packit 1f69a5
    if (end[0] != 0xff && end[1] != 0xd9) {
Packit 1f69a5
      GST_DEBUG_OBJECT (rtpjpegdepay, "no EOI marker, adding one");
Packit 1f69a5
Packit 1f69a5
      /* no EOI marker, add one */
Packit 1f69a5
      outbuf = gst_buffer_new_and_alloc (2);
Packit 1f69a5
      gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
Packit 1f69a5
      map.data[0] = 0xff;
Packit 1f69a5
      map.data[1] = 0xd9;
Packit 1f69a5
      gst_buffer_unmap (outbuf, &map);
Packit 1f69a5
Packit 1f69a5
      gst_adapter_push (rtpjpegdepay->adapter, outbuf);
Packit 1f69a5
      avail += 2;
Packit 1f69a5
    }
Packit 1f69a5
    outbuf = gst_adapter_take_buffer (rtpjpegdepay->adapter, avail);
Packit 1f69a5
Packit 1f69a5
    if (rtpjpegdepay->discont) {
Packit 1f69a5
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
Packit 1f69a5
      rtpjpegdepay->discont = FALSE;
Packit 1f69a5
    }
Packit 1f69a5
Packit 1f69a5
    gst_rtp_drop_non_video_meta (rtpjpegdepay, outbuf);
Packit 1f69a5
Packit 1f69a5
    GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  return outbuf;
Packit 1f69a5
Packit 1f69a5
  /* ERRORS */
Packit 1f69a5
empty_packet:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
Packit 1f69a5
        ("Empty Payload."), (NULL));
Packit 1f69a5
    return NULL;
Packit 1f69a5
  }
Packit 1f69a5
invalid_dimension:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
Packit 1f69a5
        ("Invalid Dimension %dx%d.", width, height), (NULL));
Packit 1f69a5
    return NULL;
Packit 1f69a5
  }
Packit 1f69a5
no_qtable:
Packit 1f69a5
  {
Packit 1f69a5
    GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
Packit 1f69a5
    return NULL;
Packit 1f69a5
  }
Packit 1f69a5
invalid_packet:
Packit 1f69a5
  {
Packit 1f69a5
    GST_WARNING_OBJECT (rtpjpegdepay, "invalid packet");
Packit 1f69a5
    gst_adapter_flush (rtpjpegdepay->adapter,
Packit 1f69a5
        gst_adapter_available (rtpjpegdepay->adapter));
Packit 1f69a5
    return NULL;
Packit 1f69a5
  }
Packit 1f69a5
no_header_packet:
Packit 1f69a5
  {
Packit 1f69a5
    GST_WARNING_OBJECT (rtpjpegdepay,
Packit 1f69a5
        "discarding data packets received when we have no header");
Packit 1f69a5
    return NULL;
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
Packit 1f69a5
static GstStateChangeReturn
Packit 1f69a5
gst_rtp_jpeg_depay_change_state (GstElement * element,
Packit 1f69a5
    GstStateChange transition)
Packit 1f69a5
{
Packit 1f69a5
  GstRtpJPEGDepay *rtpjpegdepay;
Packit 1f69a5
  GstStateChangeReturn ret;
Packit 1f69a5
Packit 1f69a5
  rtpjpegdepay = GST_RTP_JPEG_DEPAY (element);
Packit 1f69a5
Packit 1f69a5
  switch (transition) {
Packit 1f69a5
    case GST_STATE_CHANGE_READY_TO_PAUSED:
Packit 1f69a5
      gst_rtp_jpeg_depay_reset (rtpjpegdepay);
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
Packit 1f69a5
Packit 1f69a5
  switch (transition) {
Packit 1f69a5
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
  return ret;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
Packit 1f69a5
gboolean
Packit 1f69a5
gst_rtp_jpeg_depay_plugin_init (GstPlugin * plugin)
Packit 1f69a5
{
Packit 1f69a5
  return gst_element_register (plugin, "rtpjpegdepay",
Packit 1f69a5
      GST_RANK_SECONDARY, GST_TYPE_RTP_JPEG_DEPAY);
Packit 1f69a5
}