summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmerican Dynamics <GStreamer-Bugs@tycosp.com>2010-09-10 11:35:53 -0400
committerWim Taymans <wim.taymans@collabora.co.uk>2010-09-13 16:47:23 +0200
commit0f3151c73bbe6708444c0fca4be93c217996fada (patch)
tree555ccb771d9d56c11108a77e2c46472e5fc091dd
parent8e73da10b352569e7022429b4401bf38239255ec (diff)
gstrtpjpegpay: Added Define Restart Interval (DRI) Marker
Added ability to detect and respond to a JPEG-defined DRI marker
-rw-r--r--gst/rtp/gstrtpjpegpay.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/gst/rtp/gstrtpjpegpay.c b/gst/rtp/gstrtpjpegpay.c
index b6b6507e5..b7da4ba7d 100644
--- a/gst/rtp/gstrtpjpegpay.c
+++ b/gst/rtp/gstrtpjpegpay.c
@@ -88,6 +88,7 @@ typedef enum _RtpJpegMarker RtpJpegMarker;
* @JPEG_MARKER_DHT: Define Huffman Table marker
* @JPEG_MARKER_SOS: Start of Scan marker
* @JPEG_MARKER_EOI: End of Image marker
+ * @JPEG_MARKER_DRI: Define Restart Interval marker
*
* Identifers for markers in JPEG header
*/
@@ -102,6 +103,7 @@ enum _RtpJpegMarker
JPEG_MARKER_DHT = 0xC4,
JPEG_MARKER_SOS = 0xDA,
JPEG_MARKER_EOI = 0xD9,
+ JPEG_MARKER_DRI = 0xDD
};
#define DEFAULT_JPEG_QUANT 255
@@ -182,6 +184,36 @@ typedef struct
const guint8 *data;
} RtpQuantTable;
+/*
+ * RtpRestartMarkerHeader:
+ * @restartInterval: number of MCUs that appear between restart markers
+ * @restartFirstLastCount: a combination of the first packet mark in the chunk
+ * last packet mark in the chunk and the position of the
+ * first restart interval in the current "chunk"
+ *
+ * 0 1 2 3
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Restart Interval |F|L| Restart Count |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * The restart marker header is implemented according to the following
+ * methodology specified in section 3.1.7 of rfc2435.txt.
+ *
+ * "If the restart intervals in a frame are not guaranteed to be aligned
+ * with packet boundaries, the F (first) and L (last) bits MUST be set
+ * to 1 and the Restart Count MUST be set to 0x3FFF. This indicates
+ * that a receiver MUST reassemble the entire frame before decoding it."
+ *
+ */
+
+typedef struct
+{
+ guint16 restartInterval;
+ guint16 restartFirstLastCount;
+} RtpRestartMarkerHeader;
+
+
typedef struct
{
guint8 id;
@@ -536,6 +568,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstFlowReturn ret = GST_FLOW_ERROR;
RtpJpegHeader jpeg_header;
RtpQuantHeader quant_header;
+ RtpRestartMarkerHeader restart_marker_header;
RtpQuantTable tables[15] = { {0, NULL}, };
CompInfo info[3] = { {0,}, };
guint quant_data_size;
@@ -546,7 +579,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
guint jpeg_header_size = 0;
guint offset;
gboolean frame_done;
- gboolean sos_found, sof_found, dqt_found;
+ gboolean sos_found, sof_found, dqt_found, dri_found;
gint i;
GstBufferList *list = NULL;
GstBufferListIterator *it = NULL;
@@ -566,6 +599,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
sos_found = FALSE;
dqt_found = FALSE;
sof_found = FALSE;
+ dri_found = FALSE;
while (!sos_found && (offset < size)) {
GST_LOG_OBJECT (pay, "checking from offset %u", offset);
@@ -597,6 +631,14 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
case JPEG_MARKER_SOI:
GST_LOG_OBJECT (pay, "SOI found");
break;
+ case JPEG_MARKER_DRI:
+ GST_LOG_OBJECT (pay, "DRI found");
+ restart_marker_header.restartInterval=g_htons((data[offset+2] << 8) | (data[offset + 3]));
+ restart_marker_header.restartFirstLastCount=g_htons(0xFFFF);
+ if (restart_marker_header.restartInterval > 0) {
+ dri_found = TRUE;
+ }
+ break;
default:
break;
}
@@ -615,6 +657,9 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
data += jpeg_header_size;
offset = 0;
+ if (dri_found)
+ pay->type += 64;
+
/* prepare stuff for the jpeg header */
jpeg_header.type_spec = 0;
jpeg_header.type = pay->type;
@@ -659,6 +704,9 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
bytes_left = sizeof (jpeg_header) + quant_data_size + size;
+ if (dri_found)
+ bytes_left += sizeof (restart_marker_header);
+
frame_done = FALSE;
do {
GstBuffer *outbuf;
@@ -666,8 +714,13 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
guint payload_size = (bytes_left < mtu ? bytes_left : mtu);
if (pay->buffer_list) {
- outbuf = gst_rtp_buffer_new_allocate (sizeof (jpeg_header) +
+ if (dri_found){
+ outbuf = gst_rtp_buffer_new_allocate (sizeof (jpeg_header) +
+ sizeof (restart_marker_header) + quant_data_size, 0, 0);
+ } else {
+ outbuf = gst_rtp_buffer_new_allocate (sizeof (jpeg_header) +
quant_data_size, 0, 0);
+ }
} else {
outbuf = gst_rtp_buffer_new_allocate (payload_size, 0, 0);
}
@@ -692,6 +745,13 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
payload += sizeof (jpeg_header);
payload_size -= sizeof (jpeg_header);
+ if (dri_found)
+ {
+ memcpy (payload, &restart_marker_header, sizeof (restart_marker_header));
+ payload += sizeof (restart_marker_header);
+ payload_size -= sizeof (restart_marker_header);
+ }
+
/* only send quant table with first packet */
if (G_UNLIKELY (quant_data_size > 0)) {
memcpy (payload, &quant_header, sizeof (quant_header));