[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