mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-15 03:45:38 +00:00
tsmux: Simplify tsmux_section_write_packet
- Don't try to make the parameters match `GHFunc`. Use a dedicated callback for `g_hash_table_foreach`. - Don't try to be clever with buffer memories. We're allocating a full packet anyway, might as well memcpy and save on a lot of complexity. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5516>
This commit is contained in:
parent
c205086f2b
commit
77429e4096
1 changed files with 58 additions and 103 deletions
|
@ -1147,132 +1147,80 @@ tsmux_write_ts_header (TsMux * mux, guint8 * buf, TsMuxPacketInfo * pi,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The unused_arg is needed for g_hash_table_foreach() */
|
|
||||||
static gboolean
|
static gboolean
|
||||||
tsmux_section_write_packet (gpointer unused_arg,
|
tsmux_section_write_packet (TsMux * mux, TsMuxSection * section)
|
||||||
TsMuxSection * section, TsMux * mux)
|
|
||||||
{
|
{
|
||||||
GstBuffer *section_buffer;
|
|
||||||
GstBuffer *packet_buffer = NULL;
|
|
||||||
GstMemory *mem;
|
|
||||||
guint8 *packet;
|
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
gsize data_size = 0;
|
gsize data_size;
|
||||||
gsize payload_written;
|
guint payload_written = 0;
|
||||||
guint len = 0, offset = 0, payload_len = 0;
|
gboolean ret = FALSE;
|
||||||
guint extra_alloc_bytes = 0;
|
|
||||||
|
|
||||||
g_return_val_if_fail (section != NULL, FALSE);
|
g_return_val_if_fail (section != NULL, FALSE);
|
||||||
g_return_val_if_fail (mux != NULL, FALSE);
|
g_return_val_if_fail (mux != NULL, FALSE);
|
||||||
|
|
||||||
|
data = gst_mpegts_section_packetize (section->section, &data_size);
|
||||||
|
if (!data) {
|
||||||
|
GST_WARNING ("Could not packetize section");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark the start of new PES unit */
|
/* Mark the start of new PES unit */
|
||||||
section->pi.packet_start_unit_indicator = TRUE;
|
section->pi.packet_start_unit_indicator = TRUE;
|
||||||
|
|
||||||
data = gst_mpegts_section_packetize (section->section, &data_size);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
TS_DEBUG ("Could not packetize section");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark payload data size */
|
/* Mark payload data size */
|
||||||
section->pi.stream_avail = data_size;
|
section->pi.stream_avail = data_size;
|
||||||
payload_written = 0;
|
|
||||||
|
|
||||||
/* Wrap section data in a buffer without free function.
|
|
||||||
The data will be freed when the GstMpegtsSection is destroyed. */
|
|
||||||
section_buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
|
|
||||||
data, data_size, 0, data_size, NULL, NULL);
|
|
||||||
|
|
||||||
TS_DEBUG ("Section buffer with size %" G_GSIZE_FORMAT " created",
|
|
||||||
gst_buffer_get_size (section_buffer));
|
|
||||||
|
|
||||||
while (section->pi.stream_avail > 0) {
|
while (section->pi.stream_avail > 0) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstMapInfo map;
|
||||||
|
guint len, offset;
|
||||||
|
|
||||||
packet = g_malloc (TSMUX_PACKET_LENGTH);
|
if (!tsmux_get_buffer (mux, &buf))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!gst_buffer_map (buf, &map, GST_MAP_WRITE)) {
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (section->pi.packet_start_unit_indicator) {
|
if (section->pi.packet_start_unit_indicator) {
|
||||||
/* Wee need room for a pointer byte */
|
/* We need room for a pointer byte */
|
||||||
section->pi.stream_avail++;
|
if (!tsmux_write_ts_header (mux, map.data, §ion->pi,
|
||||||
|
section->pi.stream_avail + 1, &len, &offset)) {
|
||||||
if (!tsmux_write_ts_header (mux, packet, §ion->pi,
|
gst_buffer_unmap (buf, &map);
|
||||||
section->pi.stream_avail, &len, &offset))
|
gst_buffer_unref (buf);
|
||||||
goto fail;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write the pointer byte */
|
/* Write the pointer byte */
|
||||||
packet[offset++] = 0x00;
|
map.data[offset++] = 0x00;
|
||||||
payload_len = len - 1;
|
len--;
|
||||||
|
} else if (!tsmux_write_ts_header (mux, map.data, §ion->pi,
|
||||||
} else {
|
section->pi.stream_avail, &len, &offset)) {
|
||||||
if (!tsmux_write_ts_header (mux, packet, §ion->pi,
|
gst_buffer_unmap (buf, &map);
|
||||||
section->pi.stream_avail, &len, &offset))
|
gst_buffer_unref (buf);
|
||||||
goto fail;
|
goto done;
|
||||||
payload_len = len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrap the TS header and adaption field in a GstMemory */
|
GST_DEBUG ("Creating section packet for offset %u with length %u; %u bytes"
|
||||||
mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
" remaining", payload_written, len, section->pi.stream_avail - len);
|
||||||
packet, TSMUX_PACKET_LENGTH, 0, offset, packet, g_free);
|
|
||||||
|
|
||||||
TS_DEBUG ("Creating packet buffer at offset "
|
memcpy (map.data + offset, data + payload_written, len);
|
||||||
"%" G_GSIZE_FORMAT " with length %u", payload_written, payload_len);
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
/* If in M2TS mode, we will need to resize to 4 bytes after the end
|
|
||||||
of the buffer. For performance reasons, we will now try to include
|
|
||||||
4 extra bytes from the source buffer, then resize down, to avoid
|
|
||||||
having an extra 4 byte GstMemory appended. If the source buffer
|
|
||||||
does not have enough data for this, a new GstMemory will be used */
|
|
||||||
if (gst_buffer_get_size (section_buffer) - (payload_written +
|
|
||||||
payload_len) >= 4) {
|
|
||||||
/* enough space */
|
|
||||||
extra_alloc_bytes = 4;
|
|
||||||
} else {
|
|
||||||
extra_alloc_bytes = 0;
|
|
||||||
}
|
|
||||||
packet_buffer = gst_buffer_copy_region (section_buffer, GST_BUFFER_COPY_ALL,
|
|
||||||
payload_written, payload_len + extra_alloc_bytes);
|
|
||||||
|
|
||||||
/* Prepend the header to the section data */
|
|
||||||
gst_buffer_prepend_memory (packet_buffer, mem);
|
|
||||||
|
|
||||||
/* add an extra 4 bytes if it could not be reserved already */
|
|
||||||
if (extra_alloc_bytes == 4) {
|
|
||||||
/* we allocated those already, resize */
|
|
||||||
gst_buffer_set_size (packet_buffer,
|
|
||||||
gst_buffer_get_size (packet_buffer) - extra_alloc_bytes);
|
|
||||||
} else {
|
|
||||||
void *ptr = g_malloc (4);
|
|
||||||
GstMemory *extra =
|
|
||||||
gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, ptr, 4, 0, 0, ptr,
|
|
||||||
g_free);
|
|
||||||
gst_buffer_append_memory (packet_buffer, extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_DEBUG ("Writing %d bytes to section. %d bytes remaining",
|
|
||||||
len, section->pi.stream_avail - len);
|
|
||||||
|
|
||||||
/* Push the packet without PCR */
|
/* Push the packet without PCR */
|
||||||
if (G_UNLIKELY (!tsmux_packet_out (mux, packet_buffer, -1))) {
|
if (G_UNLIKELY (!tsmux_packet_out (mux, buf, -1)))
|
||||||
/* Buffer given away */
|
goto done;
|
||||||
packet_buffer = NULL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_buffer = NULL;
|
|
||||||
section->pi.stream_avail -= len;
|
section->pi.stream_avail -= len;
|
||||||
payload_written += payload_len;
|
payload_written += len;
|
||||||
section->pi.packet_start_unit_indicator = FALSE;
|
section->pi.packet_start_unit_indicator = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_buffer_unref (section_buffer);
|
ret = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
done:
|
||||||
|
return ret;
|
||||||
fail:
|
|
||||||
g_free (packet);
|
|
||||||
if (section_buffer)
|
|
||||||
gst_buffer_unref (section_buffer);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1301,22 +1249,29 @@ tsmux_send_section (TsMux * mux, GstMpegtsSection * section)
|
||||||
tsmux_section.section = section;
|
tsmux_section.section = section;
|
||||||
tsmux_section.pi.pid = section->pid;
|
tsmux_section.pi.pid = section->pid;
|
||||||
|
|
||||||
ret = tsmux_section_write_packet (NULL, &tsmux_section, mux);
|
ret = tsmux_section_write_packet (mux, &tsmux_section);
|
||||||
gst_mpegts_section_unref (section);
|
gst_mpegts_section_unref (section);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tsmux_write_si_foreach (gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
GstMpegtsSectionType section_type = GPOINTER_TO_INT (key);
|
||||||
|
TsMuxSection *section = value;
|
||||||
|
TsMux *mux = user_data;
|
||||||
|
|
||||||
|
if (!tsmux_section_write_packet (mux, section))
|
||||||
|
GST_WARNING ("Failed to send SI section (type %d)", section_type);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
tsmux_write_si (TsMux * mux)
|
tsmux_write_si (TsMux * mux)
|
||||||
{
|
{
|
||||||
g_hash_table_foreach (mux->si_sections,
|
g_hash_table_foreach (mux->si_sections, tsmux_write_si_foreach, mux);
|
||||||
(GHFunc) tsmux_section_write_packet, mux);
|
|
||||||
|
|
||||||
mux->si_changed = FALSE;
|
mux->si_changed = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1753,7 +1708,7 @@ tsmux_write_pat (TsMux * mux)
|
||||||
mux->pat_changed = FALSE;
|
mux->pat_changed = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tsmux_section_write_packet (NULL, &mux->pat, mux);
|
return tsmux_section_write_packet (mux, &mux->pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1853,7 +1808,7 @@ tsmux_write_pmt (TsMux * mux, TsMuxProgram * program)
|
||||||
program->pmt.section->version_number = program->pmt_version++;
|
program->pmt.section->version_number = program->pmt_version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tsmux_section_write_packet (NULL, &program->pmt, mux);
|
return tsmux_section_write_packet (mux, &program->pmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1861,7 +1816,7 @@ tsmux_write_scte_null (TsMux * mux, TsMuxProgram * program)
|
||||||
{
|
{
|
||||||
/* SCTE-35 NULL section is created when PID is set */
|
/* SCTE-35 NULL section is created when PID is set */
|
||||||
GST_LOG ("Writing SCTE NULL packet");
|
GST_LOG ("Writing SCTE NULL packet");
|
||||||
return tsmux_section_write_packet (NULL, program->scte35_null_section, mux);
|
return tsmux_section_write_packet (mux, program->scte35_null_section);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue