View Single Post
Old 15th November 2013, 07:06   #7  |  Link
drmpeg
Registered User
 
Join Date: Jan 2003
Location: Silicon Valley
Posts: 455
If you're interested in rate control, then you need to know the size of each picture in a H.264 bitstream. Here's some C code to get you started.
Code:
/*
H.264 picture size parser
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>

#define    TRUE    1
#define    FALSE   0

int main(int argc, char **argv)
{
    FILE    *fp;
    static unsigned char    buffer[16384];
    int    i, length;
    static int    first = TRUE;
    static unsigned int    parse = 0;
    unsigned int    picture_size = 0;

    if (argc != 2) {
        fprintf(stderr, "usage: bits <infile>\n");
        exit(-1);
    }

    /*--- open binary file (for parsing) ---*/
    fp = fopen(argv[1], "rb");
    if (fp == 0) {
        fprintf(stderr, "Cannot open bitstream file <%s>\n", argv[1]);
        exit(-1);
    }

    while(!feof(fp))  {
        length = fread(&buffer[0], 1, 16384, fp);
        for(i = 0; i < length; i++)  {
            parse = (parse << 8) + buffer[i];
            if ((parse & 0xffffff00) == 0x00000100)  {    /* look for a start code */
                if ((parse & 0xffffff9f) == 0x00000101 || (parse & 0xffffff9f) == 0x00000105)  {    /* look for a coded slice */
                    i++;
                    picture_size++;
                    parse = (parse << 8) + buffer[i];
                    if (parse & 0x00000080)  {    /* make sure it's the first slice of a picture */
                        if (first == TRUE)  {
                            first = FALSE;
                            picture_size = 0;
                        }
                        else  {
                            printf("%8d\n", picture_size * 8);
                            picture_size = 0;
                        }
                    }
                }
            }
            picture_size++;
        }
    }
    fclose(fp);
    return 0;
}
Once you know the size of each picture, it's easy to calculate the VBV occupancy.

1) Initialize the size of the VBV buffer (in bits). Either to full or some percentage of full.

2) Subtract the size of a picture (in bits) from the VBV. Check to see if the VBV buffer fullness is zero or less than zero. If zero or less than zero, it's a VBV underflow.

3) Add the number of bits based on the VBV rate. For example, if the vbv-maxrate is 10,000,000 bits/second and the frame rate is 25 frames/second, then add 400,000 bits. If the stream is really CBR (in x264, you need to explicitly turn on picture stuffing), then you should not exceed the size of the VBV buffer. If you exceed the size of the VBV buffer, it's a VBV overflow. For VBR streams (or CBR stream without picture stuffing), there is no VBV overflow and you just set the VBV level back to full on an overflow.

4) Repeat steps 2 and 3 for the entire bitstream. Note that the number of bits to add on step 3 is based on frame rate. Therefore, VBV doesn't apply to variable frame rate and telecine flags need to be accounted for. Also, if the frame rate is not an integer (like 29.97 fps), then be sure to use floating point math and add fractional bits back to the VBV.

Ron
__________________
HD MPEG-2 Test Patterns http://www.w6rz.net
drmpeg is offline   Reply With Quote