mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 08:08:22 +00:00
gstrtpjpegpay: Added Define Restart Interval (DRI) Marker
Added ability to detect and respond to a JPEG-defined DRI marker
This commit is contained in:
parent
8e73da10b3
commit
0f3151c73b
1 changed files with 62 additions and 2 deletions
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue