mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
rtph264pay: implement full bytestream scan mode.
Implement the full bytestream scan mode. Fixes #634910
This commit is contained in:
parent
fdfe76ac53
commit
9d52c1a1d7
2 changed files with 66 additions and 11 deletions
|
@ -66,7 +66,7 @@ gst_h264_scan_mode_get_type (void)
|
||||||
static GType h264_scan_mode_type = 0;
|
static GType h264_scan_mode_type = 0;
|
||||||
static const GEnumValue h264_scan_modes[] = {
|
static const GEnumValue h264_scan_modes[] = {
|
||||||
{GST_H264_SCAN_MODE_BYTESTREAM,
|
{GST_H264_SCAN_MODE_BYTESTREAM,
|
||||||
"Scan complete bytestream for NALUs (not implemented)",
|
"Scan complete bytestream for NALUs",
|
||||||
"bytestream"},
|
"bytestream"},
|
||||||
{GST_H264_SCAN_MODE_MULTI_NAL, "Buffers contain multiple complete NALUs",
|
{GST_H264_SCAN_MODE_MULTI_NAL, "Buffers contain multiple complete NALUs",
|
||||||
"multiple"},
|
"multiple"},
|
||||||
|
@ -236,6 +236,11 @@ gst_rtp_h264_pay_finalize (GObject * object)
|
||||||
|
|
||||||
g_free (rtph264pay->sprop_parameter_sets);
|
g_free (rtph264pay->sprop_parameter_sets);
|
||||||
|
|
||||||
|
if (rtph264pay->adapter) {
|
||||||
|
g_object_unref (rtph264pay->adapter);
|
||||||
|
rtph264pay->adapter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,16 +916,30 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
guint8 *data, *nal_data;
|
guint8 *data, *nal_data;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
GArray *nal_queue;
|
GArray *nal_queue;
|
||||||
|
guint pushed;
|
||||||
|
|
||||||
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
||||||
|
|
||||||
/* the input buffer contains one or more NAL units */
|
/* the input buffer contains one or more NAL units */
|
||||||
size = GST_BUFFER_SIZE (buffer);
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
|
||||||
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (basepayload, "got %d bytes", size);
|
if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM) {
|
||||||
|
timestamp = gst_adapter_prev_timestamp (rtph264pay->adapter, 0);
|
||||||
|
gst_adapter_push (rtph264pay->adapter, buffer);
|
||||||
|
size = gst_adapter_available (rtph264pay->adapter);
|
||||||
|
data = gst_adapter_peek (rtph264pay->adapter, size);
|
||||||
|
GST_DEBUG_OBJECT (basepayload, "got %d bytes (%d)", size,
|
||||||
|
GST_BUFFER_SIZE (buffer));
|
||||||
|
|
||||||
|
if (!GST_CLOCK_TIME_IS_VALID (timestamp))
|
||||||
|
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
} else {
|
||||||
|
size = GST_BUFFER_SIZE (buffer);
|
||||||
|
data = GST_BUFFER_DATA (buffer);
|
||||||
|
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
GST_DEBUG_OBJECT (basepayload, "got %d bytes", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
/* now loop over all NAL units and put them in a packet
|
/* now loop over all NAL units and put them in a packet
|
||||||
* FIXME, we should really try to pack multiple NAL units into one RTP packet
|
* FIXME, we should really try to pack multiple NAL units into one RTP packet
|
||||||
|
@ -999,6 +1018,12 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
* data is unchanged by the call to next_start_code()
|
* data is unchanged by the call to next_start_code()
|
||||||
*/
|
*/
|
||||||
next = next_start_code (data, size);
|
next = next_start_code (data, size);
|
||||||
|
|
||||||
|
if (next == size
|
||||||
|
&& rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM) {
|
||||||
|
/* Didn't find the start of next NAL, handle it next time */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nal length is distance to next start code */
|
/* nal length is distance to next start code */
|
||||||
|
@ -1045,6 +1070,8 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
|
|
||||||
/* second pass to payload and push */
|
/* second pass to payload and push */
|
||||||
data = nal_data;
|
data = nal_data;
|
||||||
|
pushed = 0;
|
||||||
|
|
||||||
for (i = 0; i < nal_queue->len; i++) {
|
for (i = 0; i < nal_queue->len; i++) {
|
||||||
guint size;
|
guint size;
|
||||||
|
|
||||||
|
@ -1057,9 +1084,10 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
* starts with 0x000001 so all the 0x00 bytes at the end of this one are
|
* starts with 0x000001 so all the 0x00 bytes at the end of this one are
|
||||||
* trailing 0x0 that can be discarded */
|
* trailing 0x0 that can be discarded */
|
||||||
size = nal_len;
|
size = nal_len;
|
||||||
if (i + 1 != nal_queue->len)
|
if (i + 1 != nal_queue->len
|
||||||
for ( ; size > 1 && data[size - 1] == 0x0; size--)
|
|| rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM)
|
||||||
/* skip */;
|
for (; size > 1 && data[size - 1] == 0x0; size--)
|
||||||
|
/* skip */ ;
|
||||||
|
|
||||||
/* put the data in one or more RTP packets */
|
/* put the data in one or more RTP packets */
|
||||||
ret =
|
ret =
|
||||||
|
@ -1072,11 +1100,15 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
/* move to next NAL packet */
|
/* move to next NAL packet */
|
||||||
data += nal_len;
|
data += nal_len;
|
||||||
size -= nal_len;
|
size -= nal_len;
|
||||||
|
pushed += nal_len + 3;
|
||||||
}
|
}
|
||||||
g_array_set_size (nal_queue, 0);
|
g_array_set_size (nal_queue, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_buffer_unref (buffer);
|
if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM)
|
||||||
|
gst_adapter_flush (rtph264pay->adapter, pushed);
|
||||||
|
else
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1122,6 +1154,8 @@ gst_basertppayload_change_state (GstElement * element,
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
rtph264pay->send_spspps = FALSE;
|
rtph264pay->send_spspps = FALSE;
|
||||||
|
if (rtph264pay->adapter)
|
||||||
|
gst_adapter_clear (rtph264pay->adapter);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1132,6 +1166,24 @@ gst_basertppayload_change_state (GstElement * element,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtp_h264_pay_set_scan_mode (GstRtpH264Pay * rtph264pay,
|
||||||
|
GstH264ScanMode scan_mode)
|
||||||
|
{
|
||||||
|
if (rtph264pay->scan_mode == scan_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rtph264pay->adapter) {
|
||||||
|
g_object_unref (rtph264pay->adapter);
|
||||||
|
rtph264pay->adapter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtph264pay->scan_mode = scan_mode;
|
||||||
|
if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM) {
|
||||||
|
rtph264pay->adapter = gst_adapter_new ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
|
gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec)
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
@ -1149,7 +1201,7 @@ gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
|
||||||
rtph264pay->update_caps = TRUE;
|
rtph264pay->update_caps = TRUE;
|
||||||
break;
|
break;
|
||||||
case PROP_SCAN_MODE:
|
case PROP_SCAN_MODE:
|
||||||
rtph264pay->scan_mode = g_value_get_enum (value);
|
gst_rtp_h264_pay_set_scan_mode (rtph264pay, g_value_get_enum (value));
|
||||||
break;
|
break;
|
||||||
case PROP_BUFFER_LIST:
|
case PROP_BUFFER_LIST:
|
||||||
rtph264pay->buffer_list = g_value_get_boolean (value);
|
rtph264pay->buffer_list = g_value_get_boolean (value);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define __GST_RTP_H264_PAY_H__
|
#define __GST_RTP_H264_PAY_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
#include <gst/rtp/gstbasertppayload.h>
|
#include <gst/rtp/gstbasertppayload.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -61,6 +62,8 @@ struct _GstRtpH264Pay
|
||||||
gboolean update_caps;
|
gboolean update_caps;
|
||||||
GstH264ScanMode scan_mode;
|
GstH264ScanMode scan_mode;
|
||||||
|
|
||||||
|
GstAdapter *adapter;
|
||||||
|
|
||||||
guint spspps_interval;
|
guint spspps_interval;
|
||||||
gboolean send_spspps;
|
gboolean send_spspps;
|
||||||
GstClockTime last_spspps;
|
GstClockTime last_spspps;
|
||||||
|
|
Loading…
Reference in a new issue