WebM VP8 Codec SDK
decode_to_md5.c

Frame-by-frame MD5 Checksum

This example builds upon the simple decoder loop to show how checksums of the decoded output can be generated. These are used for validating decoder implementations against the reference implementation, for example.

MD5 algorithm

The Message-Digest 5 (MD5) is a well known hash function. We have provided an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm for your use. Our implmentation only changes the interface of this reference code. You must include the md5_utils.h header for access to these functions.

#include "md5_utils.h"

Processing The Decoded Data

Each row of the image is passed to the MD5 accumulator. First the Y plane is processed, then U, then V. It is important to honor the image’s stride values.

unsigned char  md5_sum[16];
MD5Context     md5;
int            i;
 
MD5Init(&md5);
 
for(plane=0; plane < 3; plane++) {
    unsigned char *buf =img->planes[plane];
 
    for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
        MD5Update(&md5, buf, (plane ? (img->d_w + 1) >> 1 : img->d_w));
        buf += img->stride[plane];
    }
}
 
MD5Final(md5_sum, &md5);
for(i=0; i<16; i++)
    fprintf(outfile, "%02x",md5_sum[i]);
fprintf(outfile, "  img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
        frame_cnt);

Putting It All Together

/*
    Copyright (c) 2010 The WebM project authors. All Rights Reserved.
  
    Use of this source code is governed by a BSD-style license
    that can be found in the LICENSE file in the root of the source
    tree. An additional intellectual property rights grant can be found
    in the file PATENTS.  All contributing project authors may
    be found in the AUTHORS file in the root of the source tree.
 */
 
 
/*
   This example builds upon the simple decoder loop to show how checksums
   of the decoded output can be generated. These are used for validating
   decoder implementations against the reference implementation, for example.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h"
#define interface (vpx_codec_vp8_dx())
#include "md5_utils.h"                                                        //
 
 
#define IVF_FILE_HDR_SZ  (32)
#define IVF_FRAME_HDR_SZ (12)
 
static unsigned int mem_get_le32(const unsigned char *mem) {
    return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
}
 
static void die(const char *fmt, ...) {
    va_list ap;
 
    va_start(ap, fmt);
    vprintf(fmt, ap);
    if(fmt[strlen(fmt)-1] != '\n')
        printf("\n");
    exit(EXIT_FAILURE);
}
 
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
    const char *detail = vpx_codec_error_detail(ctx);
 
    printf("%s: %s\n", s, vpx_codec_error(ctx));
    if(detail)
        printf("    %s\n",detail);
    exit(EXIT_FAILURE);
}
 
 
int main(int argc, char **argv) {
    FILE            *infile, *outfile;
    vpx_codec_ctx_t  codec;
    int              flags = 0, frame_cnt = 0;
    unsigned char    file_hdr[IVF_FILE_HDR_SZ];
    unsigned char    frame_hdr[IVF_FRAME_HDR_SZ];
    unsigned char    frame[256*1024];
    vpx_codec_err_t  res;
 
    (void)res;
    /* Open files */
    if(argc!=3)
        die("Usage: %s <infile> <outfile>\n", argv[0]);
    if(!(infile = fopen(argv[1], "rb")))
        die("Failed to open %s for reading", argv[1]);
    if(!(outfile = fopen(argv[2], "wb")))
        die("Failed to open %s for writing", argv[2]);
 
    /* Read file header */
    if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
         && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
         && file_hdr[3]=='F'))
        die("%s is not an IVF file.", argv[1]);
 
    printf("Using %s\n",vpx_codec_iface_name(interface));
    /* Initialize codec */
    if(vpx_codec_dec_init(&codec, interface, NULL, flags))
        die_codec(&codec, "Failed to initialize decoder");
 
    /* Read each frame */
    while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
        int               frame_sz = mem_get_le32(frame_hdr);
        vpx_codec_iter_t  iter = NULL;
        vpx_image_t      *img;
 
 
        frame_cnt++;
        if(frame_sz > sizeof(frame))
            die("Frame %d data too big for example code buffer", frame_sz);
        if(fread(frame, 1, frame_sz, infile) != frame_sz)
            die("Frame %d failed to read complete frame", frame_cnt);
 
        /* Decode the frame */
        if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
            die_codec(&codec, "Failed to decode frame");
 
        /* Write decoded data to disk */
        while((img = vpx_codec_get_frame(&codec, &iter))) {
            unsigned int plane, y;
 
            unsigned char  md5_sum[16];                                       //
            MD5Context     md5;                                               //
            int            i;                                                 //
                                                                              //
            MD5Init(&md5);                                                    //
                                                                              //
            for(plane=0; plane < 3; plane++) {                                //
                unsigned char *buf =img->planes[plane];                       //
                                                                              //
                for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) { //
                    MD5Update(&md5, buf, (plane ? (img->d_w + 1) >> 1 : img->d_w));//
                    buf += img->stride[plane];                                //
                }                                                             //
            }                                                                 //
                                                                              //
            MD5Final(md5_sum, &md5);                                          //
            for(i=0; i<16; i++)                                               //
                fprintf(outfile, "%02x",md5_sum[i]);                          //
            fprintf(outfile, "  img-%dx%d-%04d.i420\n", img->d_w, img->d_h,   //
                    frame_cnt);                                               //
        }
    }
    printf("Processed %d frames.\n",frame_cnt);
    if(vpx_codec_destroy(&codec))
        die_codec(&codec, "Failed to destroy codec");
 
    fclose(outfile);
    fclose(infile);
    return EXIT_SUCCESS;
}