H.264 Decoder

This article explains how you can use Transcoder to decode an AVC / H.264 elementary stream.

Source Video

For a source video we use the foreman_qcif.h264 file from the AVBlocks Samples Repository.

Code

This code takes an H.264 stream, and decodes it to raw uncompressed YUV frames.

.NET

Initialize AVBlocks

static void DecodeH264Stream()
{
    Library.Initialize();

    DecodeH264Stream("foreman_qcif.h264");

    Library.Shutdown();
}

Configure Transcoder

static void DecodeH264Stream(string inputFile)
{
    // Create an input socket from file
    var inSocket = new MediaSocket() {
        File = inputFile
    };

    // Create an output socket with one YUV 4:2:0 video pin
    var outSocket = new MediaSocket() {
        StreamType = StreamType.UncompressedVideo
    };

    outSocket.Pins.Add(new MediaPin() {
        StreamInfo = new VideoStreamInfo() {
            StreamType = StreamType.UncompressedVideo,
            ColorFormat = ColorFormat.YUV420,
            ScanType = ScanType.Progressive
        }
    });

    // Create Transcoder
    using (var transcoder = new Transcoder())
    {
        transcoder.Inputs.Add(inSocket);
        transcoder.Outputs.Add(outSocket);

        if (transcoder.Open())
        {
            DecodeH264Stream(transcoder);

            transcoder.Close();
        }
    }
}

Call Transcoder.Pull

static void DecodeH264Stream(Transcoder transcoder)
{
    int inputIndex = 0;
    var yuvFrame = new MediaSample();

    while (transcoder.Pull(out inputIndex, yuvFrame))
    {
        // Each call to Transcoder::pull returns a raw YUV 4:2:0 frame. 
        ProcessYUVFrame(yuvFrame.Buffer);
    }

}

Complete .NET Code

using System;
using System.Linq;

using PrimoSoftware.AVBlocks;

namespace H264Decoder
{
    class Program
    {
        static int frameIndex = 0;
        static void ProcessYUVFrame(MediaBuffer buffer)
        {
            // Do something with the YUV frame, 
            // for example you can save it to a file or render the frame on the screen

            Console.WriteLine("Frame Index : {0}", frameIndex);
            frameIndex++;
        }

        static void DecodeH264Stream(Transcoder transcoder)
        {
            int inputIndex = 0;
            var yuvFrame = new MediaSample();

            while (transcoder.Pull(out inputIndex, yuvFrame))
            {
                // Each call to Transcoder::pull returns a raw YUV 4:2:0 frame. 
                ProcessYUVFrame(yuvFrame.Buffer);
            }
        }

        static void DecodeH264Stream(string inputFile)
        {
            // Create an input socket from file
            var inSocket = new MediaSocket() {
                File = inputFile
            };

            // Create an output socket with one YUV 4:2:0 video pin
            var outSocket = new MediaSocket() {
                StreamType = StreamType.UncompressedVideo
            };

            outSocket.Pins.Add(new MediaPin() {
                StreamInfo = new VideoStreamInfo() {
                    StreamType = StreamType.UncompressedVideo,
                    ColorFormat = ColorFormat.YUV420,
                    ScanType = ScanType.Progressive
                }
            });

            // Create Transcoder
            using (var transcoder = new Transcoder())
            {
                transcoder.Inputs.Add(inSocket);
                transcoder.Outputs.Add(outSocket);

                if (transcoder.Open())
                {
                    DecodeH264Stream(transcoder);

                    transcoder.Close();
                }
            }
        }

        static void DecodeH264Stream()
        {
            Library.Initialize();

            DecodeH264Stream("foreman_qcif.h264");

            Library.Shutdown();
        }

        static void Main(string[] args)
        {
            DecodeH264Stream();
        }
    }
}

How to run

Follow the steps to create a C# console application in Visual Studio, but in Program.cs use the code from this article.

Download the foreman_qcif.h264 file from the AVBlocks Samples Repository and save it in bin\x64\Debug under the project's directory.

Run the application in Visual Studio.

C++

Windows

Initialize AVBlocks
void decode_h264_stream()
{
    Library::initialize();

    decode_h264_stream(L"foreman_qcif.h264");

    Library::shutdown();
}
Configure Transcoder
void decode_h264_stream(const char_t* inputFile) 
{
    // Create an input socket from file
    p::ref<MediaSocket> inSocket(Library::createMediaSocket());
    inSocket->setFile(inputFile);

    // Create an output socket with one YUV 4:2:0 video pin
    p::ref<VideoStreamInfo> outStreamInfo(Library::createVideoStreamInfo());
    outStreamInfo->setStreamType(StreamType::UncompressedVideo);
    outStreamInfo->setColorFormat(ColorFormat::YUV420);
    outStreamInfo->setScanType(ScanType::Progressive);

    p::ref<MediaPin> outPin(Library::createMediaPin());
    outPin->setStreamInfo(outStreamInfo.get());

    p::ref<MediaSocket> outSocket(Library::createMediaSocket());
    outSocket->setStreamType(StreamType::UncompressedVideo);

    outSocket->pins()->add(outPin.get());

    // Create Transcoder
    p::ref<Transcoder> transcoder(Library::createTranscoder());
    transcoder->inputs()->add(inSocket.get());
    transcoder->outputs()->add(outSocket.get());

    if (transcoder->open())
    {
        decode_h264_stream(transcoder.get());

        transcoder->close();
    }
}
Call Transcoder::pull
void decode_h264_stream(Transcoder* transcoder)
{
    int32_t inputIndex = 0;
    p::ref<MediaSample> yuvFrame(Library::createMediaSample());

    while (transcoder->pull(inputIndex, yuvFrame.get()))
    {
        // Each call to Transcoder::pull returns a raw YUV 4:2:0 frame. 
        process_yuv_frame(yuvFrame->buffer());
    }
}
Complete C++ Code
// H264Decoder.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

namespace p = primo;

using namespace primo::codecs;
using namespace primo::avblocks;

static int frame_index = 0;
void process_yuv_frame(MediaBuffer* buffer)
{
    // Do something with the YUV frame, 
    // for example you can save it to a file or render the frame on the screen

    std::wcout << L"Frame Index : " << frame_index << std::endl;
    frame_index++;
}

void decode_h264_stream(Transcoder* transcoder)
{
    int32_t inputIndex = 0;
    p::ref<MediaSample> yuvFrame(Library::createMediaSample());

    while (transcoder->pull(inputIndex, yuvFrame.get()))
    {
        // Each call to Transcoder::pull returns a raw YUV 4:2:0 frame. 
        process_yuv_frame(yuvFrame->buffer());
    }
}

void decode_h264_stream(const char_t* inputFile) 
{
    // Create an input socket from file
    p::ref<MediaSocket> inSocket(Library::createMediaSocket());
    inSocket->setFile(inputFile);

    // Create an output socket with one YUV 4:2:0 video pin
    p::ref<VideoStreamInfo> outStreamInfo(Library::createVideoStreamInfo());
    outStreamInfo->setStreamType(StreamType::UncompressedVideo);
    outStreamInfo->setColorFormat(ColorFormat::YUV420);
    outStreamInfo->setScanType(ScanType::Progressive);

    p::ref<MediaPin> outPin(Library::createMediaPin());
    outPin->setStreamInfo(outStreamInfo.get());

    p::ref<MediaSocket> outSocket(Library::createMediaSocket());
    outSocket->setStreamType(StreamType::UncompressedVideo);

    outSocket->pins()->add(outPin.get());

    // Create Transcoder
    p::ref<Transcoder> transcoder(Library::createTranscoder());
    transcoder->inputs()->add(inSocket.get());
    transcoder->outputs()->add(outSocket.get());

    if (transcoder->open())
    {
        decode_h264_stream(transcoder.get());

        transcoder->close();
    }
}

void decode_h264_stream()
{
    Library::initialize();

    decode_h264_stream(L"foreman_qcif.h264");

    Library::shutdown();
}

int _tmain(int argc, _TCHAR* argv[])
{
    decode_h264_stream();
    return 0;
}
How to run

Follow the steps to create a C++ console application in Visual Studio, but use the code from this article.

Download the foreman_qcif.h264 file from the AVBlocks Samples Repository and save it in the project directory.

Run the application in Visual Studio.


Last updated on April 8th, 2017 02:55:54 PM