gstrtpjpegpay: Added Define Restart Interval (DRI) Marker

Added ability to detect and respond to a JPEG-defined DRI marker
This commit is contained in:
American Dynamics 2010-09-10 11:35:53 -04:00 committed by Wim Taymans
parent 8e73da10b3
commit 0f3151c73b

View file

@ -88,6 +88,7 @@ typedef enum _RtpJpegMarker RtpJpegMarker;
* @JPEG_MARKER_DHT: Define Huffman Table marker * @JPEG_MARKER_DHT: Define Huffman Table marker
* @JPEG_MARKER_SOS: Start of Scan marker * @JPEG_MARKER_SOS: Start of Scan marker
* @JPEG_MARKER_EOI: End of Image marker * @JPEG_MARKER_EOI: End of Image marker
* @JPEG_MARKER_DRI: Define Restart Interval marker
* *
* Identifers for markers in JPEG header * Identifers for markers in JPEG header
*/ */
@ -102,6 +103,7 @@ enum _RtpJpegMarker
JPEG_MARKER_DHT = 0xC4, JPEG_MARKER_DHT = 0xC4,
JPEG_MARKER_SOS = 0xDA, JPEG_MARKER_SOS = 0xDA,
JPEG_MARKER_EOI = 0xD9, JPEG_MARKER_EOI = 0xD9,
JPEG_MARKER_DRI = 0xDD
}; };
#define DEFAULT_JPEG_QUANT 255 #define DEFAULT_JPEG_QUANT 255
@ -182,6 +184,36 @@ typedef struct
const guint8 *data; const guint8 *data;
} RtpQuantTable; } 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 typedef struct
{ {
guint8 id; guint8 id;
@ -536,6 +568,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstFlowReturn ret = GST_FLOW_ERROR; GstFlowReturn ret = GST_FLOW_ERROR;
RtpJpegHeader jpeg_header; RtpJpegHeader jpeg_header;
RtpQuantHeader quant_header; RtpQuantHeader quant_header;
RtpRestartMarkerHeader restart_marker_header;
RtpQuantTable tables[15] = { {0, NULL}, }; RtpQuantTable tables[15] = { {0, NULL}, };
CompInfo info[3] = { {0,}, }; CompInfo info[3] = { {0,}, };
guint quant_data_size; guint quant_data_size;
@ -546,7 +579,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
guint jpeg_header_size = 0; guint jpeg_header_size = 0;
guint offset; guint offset;
gboolean frame_done; gboolean frame_done;
gboolean sos_found, sof_found, dqt_found; gboolean sos_found, sof_found, dqt_found, dri_found;
gint i; gint i;
GstBufferList *list = NULL; GstBufferList *list = NULL;
GstBufferListIterator *it = NULL; GstBufferListIterator *it = NULL;
@ -566,6 +599,7 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
sos_found = FALSE; sos_found = FALSE;
dqt_found = FALSE; dqt_found = FALSE;
sof_found = FALSE; sof_found = FALSE;
dri_found = FALSE;
while (!sos_found && (offset < size)) { while (!sos_found && (offset < size)) {
GST_LOG_OBJECT (pay, "checking from offset %u", offset); 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: case JPEG_MARKER_SOI:
GST_LOG_OBJECT (pay, "SOI found"); GST_LOG_OBJECT (pay, "SOI found");
break; 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: default:
break; break;
} }
@ -615,6 +657,9 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
data += jpeg_header_size; data += jpeg_header_size;
offset = 0; offset = 0;
if (dri_found)
pay->type += 64;
/* prepare stuff for the jpeg header */ /* prepare stuff for the jpeg header */
jpeg_header.type_spec = 0; jpeg_header.type_spec = 0;
jpeg_header.type = pay->type; 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; bytes_left = sizeof (jpeg_header) + quant_data_size + size;
if (dri_found)
bytes_left += sizeof (restart_marker_header);
frame_done = FALSE; frame_done = FALSE;
do { do {
GstBuffer *outbuf; GstBuffer *outbuf;
@ -666,8 +714,13 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
guint payload_size = (bytes_left < mtu ? bytes_left : mtu); guint payload_size = (bytes_left < mtu ? bytes_left : mtu);
if (pay->buffer_list) { if (pay->buffer_list) {
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) + outbuf = gst_rtp_buffer_new_allocate (sizeof (jpeg_header) +
quant_data_size, 0, 0); quant_data_size, 0, 0);
}
} else { } else {
outbuf = gst_rtp_buffer_new_allocate (payload_size, 0, 0); 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 += sizeof (jpeg_header);
payload_size -= 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 */ /* only send quant table with first packet */
if (G_UNLIKELY (quant_data_size > 0)) { if (G_UNLIKELY (quant_data_size > 0)) {
memcpy (payload, &quant_header, sizeof (quant_header)); memcpy (payload, &quant_header, sizeof (quant_header));