[FFmpeg-devel] [PATCH] avformat: Add Pro-MPEG CoP #3-R2 FEC protocol
Michael Niedermayer
michael at niedermayer.cc
Sat May 14 19:33:26 CEST 2016
Hi
On Fri, May 13, 2016 at 04:30:34PM +0200, Vlad Tarca wrote:
> Pro-MPEG Code of Practice #3 release 2 forward error correction for rtp_mpegts streams
>
[...]
> +static const AVClass prompeg_class = {
> + .class_name = "prompeg",
> + .item_name = av_default_item_name,
> + .option = options,
> + .version = LIBAVUTIL_VERSION_INT,
> +};
> +
> +static void xor64(const uint8_t *in1, const uint8_t *in2, uint8_t *out, int size) {
> + const uint64_t *p1, *p2;
> + const uint8_t *q1, *q2;
> + uint64_t *px;
> + uint8_t *qx;
> + int i, n, s;
> +
> + n = size / sizeof (uint64_t);
> + s = n * sizeof (uint64_t);
> +
> + p1 = (uint64_t*) in1;
> + p2 = (uint64_t*) in2;
> + px = (uint64_t*) out;
> +
> + for (i = 0; i < n; i++) {
> + px[i] = p1[i] ^ p2[i];
this is a strict aliassing violation probably or at least it can
become one easily if any access to this array is different than
char* type
its ore robust to use union or AV_RN64A/AV_WN64A or similar
> + }
> +
> + if (s == size)
> + return;
> +
> + q1 = in1 + s;
> + q2 = in2 + s;
> + qx = out + s;
> + n = size - s;
> +
> + for (i = 0; i < n; i++) {
> + qx[i] = q1[i] ^ q2[i];
> + }
> +}
> +
> +static inline uint32_t rtp_get_ts(const uint8_t *buf) {
> + return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
AV_RB32()
> +}
> +
> +static inline uint16_t rtp_get_sn(const uint8_t *buf) {
> + return (buf[2] << 8) | buf[3];
AV_RB16()
[...]
> +static int prompeg_init(URLContext *h, const uint8_t *buf, int size) {
> + PrompegContext *s = h->priv_data;
> + int i;
> +
> + s->packet_idx = 0;
> + s->packet_idx_max = s->l * s->d;
> + s->packet_size = size;
> + s->length_recovery = size - 12;
> + s->bitstring_size = (s->length_recovery + 8) * sizeof (uint8_t);
> + s->fec_buf_len = 1 + 2 * s->l; // row + column tmp + column out
> + s->rtp_buf_size = (12 + 16 + s->length_recovery) * sizeof (uint8_t);
> + s->fec_buf = NULL;
> + s->rtp_buf = NULL;
> + s->rtp_col_sn = av_get_random_seed() & 0x0fff;
> + s->rtp_row_sn = av_get_random_seed() & 0x0fff;
you need only one call, it contains enough bits
av_get_random_seed() is slow
also a bitexact mode as in AVFMT_FLAG_BITEXACT might be usefull
> +
> + s->fec_buf = av_malloc(s->fec_buf_len * sizeof (PrompegFec*));
av_malloc_array()
> + if (!s->fec_buf) {
> + goto fail;
> + }
> + for (i = 0; i < s->fec_buf_len; i++) {
> + s->fec_buf[i] = av_malloc(sizeof (PrompegFec));
> + if (!s->fec_buf[i]) {
> + goto fail;
> + }
> + s->fec_buf[i]->bitstring = av_malloc(s->bitstring_size);
> + if (!s->fec_buf[i]->bitstring) {
> + av_free(s->fec_buf[i]);
> + s->fec_buf[i] = NULL;
av_freep()
[...]
> +static int prompeg_write(URLContext *h, const uint8_t *buf, int size) {
> + PrompegContext *s = h->priv_data;
> + PrompegFec *fec_tmp;
> + uint8_t *bitstring = NULL;
> + int col_idx, col_out_idx, row_idx;
> + int ret;
> +
> + if (s->init && ((ret = prompeg_init(h, buf, size)) < 0))
> + goto fail;
> +
> + if ((ret = prompeg_create_bitstring(h, buf, size, &bitstring)) < 0)
> + goto fail;
> +
> + col_idx = s->packet_idx % s->l;
> + row_idx = s->packet_idx / s->l % s->d;
> +
> + // FEC' (row) send block-aligned, xor
> + if (col_idx == 0) {
> + if (!s->first || s->packet_idx > 0) {
> + if ((ret = prompeg_write_fec(h, s->fec_row, PROMPEG_FEC_ROW)) < 0)
> + goto fail;
> + }
> + memcpy(s->fec_row->bitstring, bitstring, s->bitstring_size);
> + s->fec_row->sn = rtp_get_sn(buf);
> + s->fec_row->ts = rtp_get_ts(buf);
> + } else {
> + xor64(s->fec_row->bitstring, bitstring, s->fec_row->bitstring,
> + s->bitstring_size);
> + }
> +
> + // FEC (column) xor
> + if (row_idx == 0) {
> + if (!s->first) {
> + // swap fec_col and fec_col_tmp
> + fec_tmp = s->fec_col[col_idx];
> + s->fec_col[col_idx] = s->fec_col_tmp[col_idx];
> + s->fec_col_tmp[col_idx] = fec_tmp;
> + }
> + memcpy(s->fec_col_tmp[col_idx]->bitstring, bitstring, s->bitstring_size);
> + s->fec_col_tmp[col_idx]->sn = rtp_get_sn(buf);
> + s->fec_col_tmp[col_idx]->ts = rtp_get_ts(buf);
> + } else {
> + xor64(s->fec_col_tmp[col_idx]->bitstring, bitstring,
> + s->fec_col_tmp[col_idx]->bitstring, s->bitstring_size);
> + }
> +
> + // FEC (column) send block-aligned
> + if (!s->first && s->packet_idx % s->d == 0) {
> + col_out_idx = s->packet_idx / s->l;
> + if ((ret = prompeg_write_fec(h, s->fec_col[col_out_idx], PROMPEG_FEC_COL)) < 0)
> + goto fail;
> + }
> +
> + if (++s->packet_idx >= s->packet_idx_max) {
> + s->packet_idx = 0;
> + if (s->first)
> + s->first = 0;
> + }
> +
> + av_free(bitstring);
> +
> + return 0;
> +
> +fail:
> + if (bitstring)
> + av_free(bitstring);
av_free(NULL) is safe
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No great genius has ever existed without some touch of madness. -- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160514/24c8a36b/attachment.sig>
More information about the ffmpeg-devel
mailing list