[FFmpeg-devel] [PATCH 5/5] lavf: add uncodedframecrc test muxer.

Nicolas George george at nsup.org
Wed Jan 15 23:30:04 CET 2014


Signed-off-by: Nicolas George <george at nsup.org>
---
 libavformat/Makefile             |   1 +
 libavformat/allformats.c         |   1 +
 libavformat/avformat.h           |   6 +-
 libavformat/uncodedframecrcenc.c | 171 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+), 3 deletions(-)
 create mode 100644 libavformat/uncodedframecrcenc.c


ALSA and XVideo are great for casual testing, not so much for valgrind.

The output matches the output of framecrc for u8 audio and packed 8-bits
video.


diff --git a/libavformat/Makefile b/libavformat/Makefile
index 383f82f..704bd62 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -387,6 +387,7 @@ OBJS-$(CONFIG_TRUEHD_MUXER)              += rawenc.o
 OBJS-$(CONFIG_TTA_DEMUXER)               += tta.o apetag.o img2.o
 OBJS-$(CONFIG_TTY_DEMUXER)               += tty.o sauce.o
 OBJS-$(CONFIG_TXD_DEMUXER)               += txd.o
+OBJS-$(CONFIG_UNCODEDFRAMECRC_MUXER)     += uncodedframecrcenc.o framehash.o
 OBJS-$(CONFIG_VC1_DEMUXER)               += rawdec.o
 OBJS-$(CONFIG_VC1_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_VC1T_DEMUXER)              += vc1test.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index f1039dd..0ee2246 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -284,6 +284,7 @@ void av_register_all(void)
     REGISTER_DEMUXER (TTA,              tta);
     REGISTER_DEMUXER (TXD,              txd);
     REGISTER_DEMUXER (TTY,              tty);
+    REGISTER_MUXER   (UNCODEDFRAMECRC,  uncodedframecrc);
     REGISTER_MUXDEMUX(VC1,              vc1);
     REGISTER_MUXDEMUX(VC1T,             vc1t);
     REGISTER_DEMUXER (VIVO,             vivo);
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 3fe6c3e..4c03985 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -460,7 +460,7 @@ typedef struct AVOutputFormat {
      * See av_write_uncoded_frame() for details.
      */
     int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
-                               AVFrame **frame, unsigned flags);
+                               AVFrame *frame, unsigned flags);
 } AVOutputFormat;
 /**
  * @}
@@ -1937,8 +1937,8 @@ int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
  * To test whether it is possible to use it with a given muxer and stream,
  * use av_write_uncoded_frame_query().
  *
- * The caller gives up ownership of the frame and must not access it
- * afterwards.
+ * The caller keeps ownership of the frame and is responsible for freeing
+ * it.
  *
  * @return  >=0 for success, a negative code on error
  */
diff --git a/libavformat/uncodedframecrcenc.c b/libavformat/uncodedframecrcenc.c
new file mode 100644
index 0000000..99d1740
--- /dev/null
+++ b/libavformat/uncodedframecrcenc.c
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2013 Nicolas George
+*
+* This file is part of FFmpeg.
+*
+* FFmpeg is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* FFmpeg is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "libavutil/adler32.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/pixdesc.h"
+#include "avformat.h"
+#include "internal.h"
+
+#define DEFINE_CRC_LINE(name, type, conv) \
+static void crc_line_ ## name(unsigned *crc, void *data, unsigned size) \
+{ \
+    type *p = data; \
+    unsigned a = *crc & 0xFFFF, b = *crc >> 16; \
+    for (; size > 0; size--, p++) { \
+        a = (a + (unsigned)(conv)) % 65521; \
+        b = (b + a) % 65521; \
+    } \
+    *crc = a | (b << 16); \
+}
+
+DEFINE_CRC_LINE(u8,  uint8_t, *p)
+DEFINE_CRC_LINE(s16, int16_t, *p + 0x8000)
+DEFINE_CRC_LINE(s32, int32_t, *p + 0x80000000)
+DEFINE_CRC_LINE(flt, float,   *p * 0x80000000 + 0x80000000)
+DEFINE_CRC_LINE(dbl, double,  *p * 0x80000000 + 0x80000000)
+
+static void video_frame_crc(AVBPrint *bp, AVFrame *frame)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
+    int i, y;
+    uint8_t *data;
+    int linesize[5] = { 0 };
+
+    av_bprintf(bp, ", %d x %d", frame->width, frame->height);
+    if (!desc) {
+        av_bprintf(bp, ", unknown");
+        return;
+    }
+    if (av_image_fill_linesizes(linesize, frame->format, frame->width) < 0)
+        return;
+    av_bprintf(bp, ", %s", desc->name);
+    for (i = 0; linesize[i]; i++) {
+        unsigned crc = 0;
+        int h = frame->height;
+        if ((i == 1 || i == 2) && desc->nb_components >= 3)
+            h = -((-h) >> desc->log2_chroma_h);
+        data = frame->data[i];
+        for (y = 0; y < h; y++) {
+            crc = av_adler32_update(crc, data, linesize[i]);
+            data += frame->linesize[i];
+        }
+        av_bprintf(bp, ", 0x%08x", crc);
+    }
+}
+
+static void audio_frame_crc(AVBPrint *bp, AVFrame *frame)
+{
+    int nb_planes, nb_samples, p;
+    const char *name;
+
+    nb_planes  = av_frame_get_channels(frame);
+    nb_samples = frame->nb_samples;
+    if (!av_sample_fmt_is_planar(frame->format)) {
+        nb_samples *= nb_planes;
+        nb_planes = 1;
+    }
+    name = av_get_sample_fmt_name(frame->format);
+    av_bprintf(bp, ", %d samples", frame->nb_samples);
+    av_bprintf(bp, ", %s", name ? name : "unknown");
+    for (p = 0; p < nb_planes; p++) {
+        uint32_t crc = 0;
+        void *d = frame->extended_data[p];
+        switch (frame->format) {
+        case AV_SAMPLE_FMT_U8:
+        case AV_SAMPLE_FMT_U8P:
+            crc_line_u8(&crc, d, nb_samples);
+            break;
+        case AV_SAMPLE_FMT_S16:
+        case AV_SAMPLE_FMT_S16P:
+            crc_line_s16(&crc, d, nb_samples);
+            break;
+        case AV_SAMPLE_FMT_S32:
+        case AV_SAMPLE_FMT_S32P:
+            crc_line_s32(&crc, d, nb_samples);
+            break;
+        case AV_SAMPLE_FMT_FLT:
+        case AV_SAMPLE_FMT_FLTP:
+            crc_line_flt(&crc, d, nb_samples);
+            break;
+        case AV_SAMPLE_FMT_DBL:
+        case AV_SAMPLE_FMT_DBLP:
+            crc_line_dbl(&crc, d, nb_samples);
+            break;
+        default:
+            av_assert0(!"reached");
+        }
+        av_bprintf(bp, ", 0x%08x", crc);
+    }
+}
+
+static int write_frame(struct AVFormatContext *s, int stream_index,
+                       AVFrame **frame, unsigned flags)
+{
+    AVBPrint bp;
+    int ret = 0;
+    enum AVMediaType type;
+    const char *type_name;
+
+    if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
+        return 0;
+
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+    av_bprintf(&bp, "%d, %10"PRId64"",
+               stream_index, (*frame)->pts);
+    type = s->streams[stream_index]->codec->codec_type;
+    type_name = av_get_media_type_string(type);
+    av_bprintf(&bp, ", %s", type_name ? type_name : "unknown");
+    switch (type) {
+        case AVMEDIA_TYPE_VIDEO:
+            video_frame_crc(&bp, *frame);
+            break;
+        case AVMEDIA_TYPE_AUDIO:
+            audio_frame_crc(&bp, *frame);
+            break;
+    }
+
+    av_bprint_chars(&bp, '\n', 1);
+    if (av_bprint_is_complete(&bp))
+        avio_write(s->pb, bp.str, bp.len);
+    else
+        ret = AVERROR(ENOMEM);
+    av_bprint_finalize(&bp, NULL);
+    return ret;
+}
+
+static int write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+    return AVERROR(ENOSYS);
+}
+
+AVOutputFormat ff_uncodedframecrc_muxer = {
+    .name              = "uncodedframecrc",
+    .long_name         = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"),
+    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
+    .video_codec       = AV_CODEC_ID_RAWVIDEO,
+    .write_header      = ff_framehash_write_header,
+    .write_packet      = write_packet,
+    .write_uncoded_frame = write_frame,
+    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+                         AVFMT_TS_NEGATIVE,
+};
-- 
1.8.5.2



More information about the ffmpeg-devel mailing list