// SPDX-License-Identifier: GPL-2.0 /* * Vidtv serves as a reference DVB driver and helps validate the existing APIs * in the media subsystem. It can also aid developers working on userspace * applications. * * This file contains the logic to translate the ES data for one access unit * from an encoder into MPEG TS packets. It does so by first encapsulating it * with a PES header and then splitting it into TS packets. * * Copyright (C) 2020 Daniel W. S. Almeida
*/
/* the flags must always be sent */
len += sizeof(struct vidtv_pes_optional);
/* From all optionals, we might send these for now */ if (send_pts && send_dts)
len += sizeof(struct vidtv_pes_optional_pts_dts); elseif (send_pts)
len += sizeof(struct vidtv_pes_optional_pts);
/* PES header length notwithstanding stuffing bytes */
len += sizeof(struct vidtv_mpeg_pes);
len += vidtv_pes_op_get_len(send_pts, send_dts);
return len;
}
static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args *args)
{ /* * This is a fixed 8-bit value equal to '0xFF' that can be inserted * by the encoder, for example to meet the requirements of the channel. * It is discarded by the decoder. No more than 32 stuffing bytes shall * be present in one PES packet header.
*/ if (args->n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) {
pr_warn_ratelimited("More than %d stuffing bytes in PES packet header\n",
PES_HEADER_MAX_STUFFING_BYTES);
args->n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES;
}
/* write the adap after the TS header */
nbytes += vidtv_memcpy(args->dest_buf,
dest_offset + nbytes,
args->dest_buf_sz,
&ts_adap, sizeof(ts_adap));
/* write the optional PCR */ if (need_pcr) {
nbytes += vidtv_pes_write_pcr_bits(args->dest_buf,
dest_offset + nbytes,
args->pcr);
*last_pcr = args->pcr;
}
/* write the stuffing bytes, if are there anything left */ if (stuff_nbytes)
nbytes += vidtv_memset(args->dest_buf,
dest_offset + nbytes,
args->dest_buf_sz,
TS_FILL_BYTE,
stuff_nbytes);
/* * The n_stuffing_bytes contain a pre-calculated value of * the amount of data that this function would read, made from * vidtv_pes_h_get_len(). If something went wrong, print a warning
*/ if (nbytes != args->n_stuffing_bytes)
pr_warn_ratelimited("write size was %d, expected %d\n",
nbytes, args->n_stuffing_bytes);
return nbytes;
}
static u32 vidtv_pes_write_ts_h(struct pes_ts_header_write_args args, bool need_pcr, u64 *last_pcr)
{ /* number of bytes written by this function */
u32 nbytes = 0; struct vidtv_mpeg_ts ts_header = {};
u16 payload_start = !args.wrote_pes_header;
if (unaligned_bytes) {
pr_warn_ratelimited("buffer is misaligned, while starting PES\n");
/* forcibly align and hope for the best */
nbytes += vidtv_memset(args->dest_buf,
args->dest_offset + nbytes,
args->dest_buf_sz,
TS_FILL_BYTE,
TS_PACKET_LEN - unaligned_bytes);
}
while (remaining_len) {
available_space = TS_PAYLOAD_LEN; /* * The amount of space initially available in the TS packet. * if this is the beginning of the PES packet, take into account * the space needed for the TS header _and_ for the PES header
*/ if (!wrote_pes_header)
available_space -= vidtv_pes_h_get_len(args->send_pts,
args->send_dts);
/* * if the encoder has inserted stuffing bytes in the PES * header, account for them.
*/
available_space -= args->n_pes_h_s_bytes;
/* Take the extra adaptation into account if need to send PCR */ if (need_pcr) {
available_space -= SIZE_PCR;
stuff_bytes = SIZE_PCR;
} else {
stuff_bytes = 0;
}
/* * how much of the _actual_ payload should be written in this * packet.
*/ if (remaining_len >= available_space) {
payload_size = available_space;
} else { /* Last frame should ensure 188-bytes PS alignment */
payload_size = remaining_len;
stuff_bytes += available_space - payload_size;
/* * Ensure that the stuff bytes will be within the * allowed range, decrementing the number of payload * bytes to write if needed.
*/ if (stuff_bytes > PES_TS_HEADER_MAX_STUFFING_BYTES) {
u32 tmp = stuff_bytes - PES_TS_HEADER_MAX_STUFFING_BYTES;
if (!wrote_pes_header) { /* write the PES header only once */
pes_header_args.dest_offset = args->dest_offset +
nbytes;
nbytes += vidtv_pes_write_h(&pes_header_args);
wrote_pes_header = true;
}
/* write as much of the payload as we possibly can */
nbytes += vidtv_memcpy(args->dest_buf,
args->dest_offset + nbytes,
args->dest_buf_sz,
args->from,
payload_size);
args->from += payload_size;
remaining_len -= payload_size;
}
return nbytes;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.