Skip to content

Repository files navigation

avblocks-cpp

AVBlocks - Audio SDK - Video SDK - C++ SDK - CLI Samples

Docs

  • API Docs — Online API reference for the AVBlocks C++ SDK
  • Wiki — Documentation and guides
  • Blog — News and updates

Installation

Download and install the AVBlocks demo version on your platform. The extracted files will be placed under the sdk/ directory of this repository.

Linux

# select version and platform
tag="v3.4.0-demo.1"
platform="linux"# download
mkdir -p ./sdk
cd ./sdk
# sdk
curl \
--location \
--output ./avblocks-$tag-$platform.tar.gz \
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.tar.gz
# sha256 checksum
curl \
--location \
--output ./avblocks-$tag-$platform.tar.gz.sha256 \
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.tar.gz.sha256
# verify sha256 checksum
shasum --check ./avblocks-$tag-$platform.tar.gz.sha256
# extract
tar -xvf avblocks-$tag-$platform.tar.gz
cd ..

macOS

# select version and platform
tag="v3.4.0-demo.1"
platform="darwin"# download
mkdir -p ./sdk
cd ./sdk
# sdk
curl \
--location \
--output ./avblocks-$tag-$platform.zip \
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.zip
# sha256 checksum
curl \
--location \
--output ./avblocks-$tag-$platform.zip.sha256 \
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.zip.sha256
# verify sha256 checksum
shasum --check ./avblocks-$tag-$platform.zip.sha256
# unzip
unzip avblocks-$tag-$platform.zip
cd ..

Windows

Scripts are PowerShell

# select version and platform$tag='v3.4.0-demo.1'$platform='windows'# downloadnew-item-Force -ItemType Directory ./sdk
cd ./sdk
# sdkcurl.exe`--location `--output ./avblocks-$tag-$platform.zip`
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.zip# sha256 checksumcurl.exe`--location `--output ./avblocks-$tag-$platform.zip.sha256`
https://github.com/avblocks/avblocks-core/releases/download/$tag/avblocks-$tag-$platform.zip.sha256# verify checksum$downloadedHash= (Get-FileHash-Algorithm SHA256 ./avblocks-$tag-$platform.zip).Hash.ToLower()
$expectedHash= (Get-Content ./avblocks-$tag-$platform.zip.sha256).Split('')[0].ToLower()
if ($downloadedHash-eq$expectedHash) { Write-Host"Checksum OK!"; } else { Write-Host"Checksum failed!"; }
# unzipexpand-archive-Force -Path avblocks-$tag-$platform.zip-DestinationPath .
cd ..

For more details, see the platform-specific setup guides in docs/.

Usage

Quick Start

Library Initialization

AVBlocks must be initialized before use and shut down when done:

#include<primo/avblocks/avb.h>intmain() {
// Initialize AVBlocksprimo::avblocks::Library::initialize();
// Set license (optional for demo)// primo::avblocks::Library::setLicense("YOUR-LICENSE-KEY");// Enable demo mode for testing without license
transcoder->setAllowDemoMode(true);
// Your code here// Shutdown AVBlocksprimo::avblocks::Library::shutdown();
return0;
}

Core Concepts

MediaSocket

A MediaSocket represents an input or output container/file with specific media parameters. It acts as a collection of media streams (via MediaPin objects) and defines the container format.

// Create a media socket
primo::ref<MediaSocket> socket(Library::createMediaSocket());
// Set file path
socket->setFile(primo::ustring("video.mp4"));
// Set container type
socket->setStreamType(StreamType::MP4);
// Create socket from presetauto socket = primo::make_ref(Library::createMediaSocket("mp4.h264.aac"));

MediaPin

A MediaPin represents a single media stream (audio or video) within a MediaSocket. Each pin has a StreamInfo object that describes the stream's properties (codec, resolution, sample rate, etc.).

// Create a pin for video
primo::ref<MediaPin> pin(Library::createMediaPin());
// Create and configure video stream info
primo::ref<VideoStreamInfo> vsi(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::H264);
vsi->setFrameWidth(1920);
vsi->setFrameHeight(1080);
vsi->setFrameRate(30.0);
// Attach stream info to pin
pin->setStreamInfo(vsi.get());
// Add pin to socket
socket->pins()->add(pin.get());
// Access pins from a socket
MediaPinList* pins = socket->pins();
int pinCount = pins->count();
MediaPin* firstPin = pins->at(0);

StreamInfo

StreamInfo and its subclasses (VideoStreamInfo, AudioStreamInfo) describe the properties of a media stream:

// Video stream info
primo::ref<VideoStreamInfo> vsi(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::H264);
vsi->setStreamSubType(StreamSubType::AVC_Annex_B);
vsi->setFrameWidth(1920);
vsi->setFrameHeight(1080);
vsi->setFrameRate(30.0);
vsi->setColorFormat(ColorFormat::YUV420);
vsi->setScanType(ScanType::Progressive);
vsi->setBitrate(2000000); // 2 Mbps// Audio stream info
primo::ref<AudioStreamInfo> asi(Library::createAudioStreamInfo());
asi->setStreamType(StreamType::AAC);
asi->setSampleRate(44100);
asi->setChannels(2);
asi->setBitsPerSample(16);
asi->setBitrate(128000); // 128 kbps// Get info properties
MediaType::Enum mediaType = si->mediaType(); // Video or Audio
StreamType::Enum streamType = si->streamType();
double duration = si->duration();
int id = si->ID();

MediaInfo

MediaInfo is used to probe media files and extract information about containers, streams, and metadata without performing transcoding.

// Create MediaInfo object
primo::ref<MediaInfo> info(Library::createMediaInfo());
// Set input file
info->inputs()->at(0)->setFile(primo::ustring("video.mp4"));
// Open and analyze the fileif (info->open()) {
// Access container information
MediaSocket* socket = info->outputs()->at(0);
StreamType::Enum containerType = socket->streamType();
// Iterate through streamsfor (int i = 0; i < socket->pins()->count(); i++) {
MediaPin* pin = socket->pins()->at(i);
StreamInfo* si = pin->streamInfo();
if (si->mediaType() == MediaType::Video) {
VideoStreamInfo* vsi = static_cast<VideoStreamInfo*>(si);
int width = vsi->frameWidth();
int height = vsi->frameHeight();
double fps = vsi->frameRate();
double duration = vsi->duration();
ColorFormat::Enum colorFormat = vsi->colorFormat();
ScanType::Enum scanType = vsi->scanType();
}
elseif (si->mediaType() == MediaType::Audio) {
AudioStreamInfo* asi = static_cast<AudioStreamInfo*>(si);
int sampleRate = asi->sampleRate();
int channels = asi->channels();
int bitsPerSample = asi->bitsPerSample();
int bitrate = asi->bitrate();
}
}
}
// Create input socket from MediaInfo
primo::ref<MediaSocket> inputSocket(Library::createMediaSocket(info.get()));

Transcoder

The Transcoder class performs media conversion between input and output sockets. It supports three modes of operation:

  1. Run Mode: Simple one-shot transcoding - transcoder->run()
  2. Push Mode: Feed data to the transcoder manually - transcoder->push()
  3. Pull Mode: Extract encoded/decoded data frame by frame - transcoder->pull()
primo::ref<Transcoder> transcoder(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
printError("Transcoder open", transcoder->error());
returnfalse;
}

MediaSample and MediaBuffer

MediaSample represents a single unit of media data (audio frame or video frame) with timing information. MediaBuffer holds the actual media data.

// Create a media sample
primo::ref<MediaSample> sample(Library::createMediaSample());
// Create and attach a buffer
primo::ref<MediaBuffer> buffer(Library::createMediaBuffer(dataSize));
uint8_t* data = buffer->start();
memcpy(data, sourceData, dataSize);
buffer->setData(0, dataSize);
sample->setBuffer(buffer.get());
// Set timestamps (in seconds)
sample->setStartTime(0.0);
// Attach external buffer without copy
std::vector<uint8_t> externalData(1024);
buffer->attach(externalData.data(), externalData.size(), true);
// Read buffer dataconstuint8_t* readData = sample->buffer()->data();
int readSize = sample->buffer()->dataSize();

Common Patterns

Getting Media Information

Extract stream information from a media file:

#include<primo/avblocks/avb.h>
#include<primo/platform/reference++.h>usingnamespaceprimo::avblocks;usingnamespaceprimo::codecs;
primo::ref<MediaInfo> info(Library::createMediaInfo());
info->inputs()->at(0)->setFile(primo::ustring("input.mp4"));
if (info->open()) {
MediaSocket* socket = info->outputs()->at(0);
// Container type
StreamType::Enum containerType = socket->streamType();
std::cout << "Container: " << getStreamTypeName(containerType) << std::endl;
// Iterate through all streamsfor (int i = 0; i < socket->pins()->count(); i++) {
MediaPin* pin = socket->pins()->at(i);
StreamInfo* si = pin->streamInfo();
std::cout << "Stream #" << i << "" << getMediaTypeName(si->mediaType()) << std::endl;
if (si->mediaType() == MediaType::Video) {
VideoStreamInfo* vsi = static_cast<VideoStreamInfo*>(si);
std::cout << " Frame size: " << vsi->frameWidth() << "x" << vsi->frameHeight() << std::endl;
std::cout << " Frame rate: " << vsi->frameRate() << std::endl;
std::cout << " Duration: " << vsi->duration() << " seconds" << std::endl;
std::cout << " Bitrate: " << vsi->bitrate() << std::endl;
std::cout << " Color format: " << getColorFormatName(vsi->colorFormat()) << std::endl;
std::cout << " Scan type: " << getScanTypeName(vsi->scanType()) << std::endl;
}
elseif (si->mediaType() == MediaType::Audio) {
AudioStreamInfo* asi = static_cast<AudioStreamInfo*>(si);
std::cout << " Sample rate: " << asi->sampleRate() << std::endl;
std::cout << " Channels: " << asi->channels() << std::endl;
std::cout << " Bits per sample: " << asi->bitsPerSample() << std::endl;
std::cout << " Bitrate: " << asi->bitrate() << std::endl;
std::cout << " Duration: " << asi->duration() << " seconds" << std::endl;
}
}
}

Decoding Video (Run Mode)

Decode H.264/AVC video to raw YUV format using simple run mode:

usingnamespaceprimo::avblocks;usingnamespaceprimo::codecs;// Use MediaInfo to get input properties
primo::ref<MediaInfo> info(Library::createMediaInfo());
info->inputs()->at(0)->setFile(primo::ustring("input.h264"));
if (!info->open()) {
printError("MediaInfo open", info->error());
returnfalse;
}
// Create input socket from MediaInfo
primo::ref<MediaSocket> inputSocket(Library::createMediaSocket(info.get()));
// Create output socket for YUVauto outputSocket = primo::make_ref(Library::createMediaSocket());
outputSocket->setFile(primo::ustring("output.yuv"));
outputSocket->setStreamType(StreamType::UncompressedVideo);
auto pin = primo::make_ref(Library::createMediaPin());
auto vsi = primo::make_ref(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::UncompressedVideo);
vsi->setColorFormat(ColorFormat::YUV420);
pin->setStreamInfo(vsi.get());
outputSocket->pins()->add(pin.get());
// Create and configure transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
printError("Transcoder open", transcoder->error());
returnfalse;
}
// Simple run - transcodes entire fileif (!transcoder->run()) {
printError("Transcoder run", transcoder->error());
returnfalse;
}
transcoder->close();

Decoding Video (Pull Mode)

Decode video and extract frames one by one:

// Setup input and output sockets (same as run mode)// ...auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Pull decoded frames one by oneint32_t outputIndex = 0;
auto sample = primo::make_ref(Library::createMediaSample());
while (transcoder->pull(outputIndex, sample.get())) {
// Process decoded frame
MediaBuffer* buffer = sample->buffer();
constuint8_t* data = buffer->data();
int dataSize = buffer->dataSize();
// Write to file or process further
outputFile.write((constchar*)data, dataSize);
}
// Check if we reached end of streamconst primo::error::ErrorInfo* error = transcoder->error();
if (error->facility() == primo::error::ErrorFacility::Codec &&
error->code() == primo::codecs::CodecError::EOS) {
// Successfully reached end of stream
std::cout << "Success" << std::endl;
}
else {
printError("Transcoder pull", error);
}
transcoder->close();

Encoding Video (Run Mode)

Encode raw YUV video to H.264/AVC:

// Create input socket for YUVauto inputSocket = primo::make_ref(Library::createMediaSocket());
inputSocket->setStreamType(StreamType::UncompressedVideo);
inputSocket->setFile(primo::ustring("input.yuv"));
auto inPin = primo::make_ref(Library::createMediaPin());
auto inVsi = primo::make_ref(Library::createVideoStreamInfo());
inVsi->setStreamType(StreamType::UncompressedVideo);
inVsi->setColorFormat(ColorFormat::YUV420);
inVsi->setFrameWidth(1920);
inVsi->setFrameHeight(1080);
inVsi->setFrameRate(30.0);
inVsi->setScanType(ScanType::Progressive);
inPin->setStreamInfo(inVsi.get());
inputSocket->pins()->add(inPin.get());
// Create output socket for H.264auto outputSocket = primo::make_ref(Library::createMediaSocket());
outputSocket->setFile(primo::ustring("output.h264"));
outputSocket->setStreamType(StreamType::H264);
auto outPin = primo::make_ref(Library::createMediaPin());
auto outVsi = primo::make_ref(Library::createVideoStreamInfo());
outVsi->setStreamType(StreamType::H264);
outVsi->setStreamSubType(StreamSubType::AVC_Annex_B);
outPin->setStreamInfo(outVsi.get());
outputSocket->pins()->add(outPin.get());
// Create and run transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
if (!transcoder->run()) {
returnfalse;
}
transcoder->close();

Encoding Video (Pull Mode)

Encode video and extract encoded packets frame by frame:

// Setup input and output sockets// ...
std::ofstream outfile("output.h264", std::ios::binary);
auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Pull encoded samplesint32_t outputIndex = 0;
auto sample = primo::make_ref(Library::createMediaSample());
while (transcoder->pull(outputIndex, sample.get())) {
// Write encoded data
outfile.write((constchar*)sample->buffer()->data(), sample->buffer()->dataSize());
}
const primo::error::ErrorInfo* error = transcoder->error();
if (error->facility() == primo::error::ErrorFacility::Codec &&
error->code() == primo::codecs::CodecError::EOS) {
// Success
}
transcoder->close();
outfile.close();

Encoding Video (Push Mode)

Feed raw frames to encoder manually:

// Output socket for H.264// ...// Input socket without file (we'll push data manually)auto inputSocket = primo::make_ref(Library::createMediaSocket());
inputSocket->setStreamType(StreamType::UncompressedVideo);
auto pin = primo::make_ref(Library::createMediaPin());
auto vsi = primo::make_ref(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::UncompressedVideo);
vsi->setColorFormat(ColorFormat::YUV420);
vsi->setFrameWidth(1920);
vsi->setFrameHeight(1080);
vsi->setFrameRate(30.0);
vsi->setScanType(ScanType::Progressive);
pin->setStreamInfo(vsi.get());
inputSocket->pins()->add(pin.get());
auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Push frames manuallyauto sample = primo::make_ref(Library::createMediaSample());
for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
// Read or generate frame data
std::vector<uint8_t> frameData = getFrameData(frameIndex);
auto buffer = primo::make_ref(Library::createMediaBuffer());
buffer->attach(frameData.data(), frameData.size(), true);
sample->setBuffer(buffer.get());
// Set presentation timestamp (required)
sample->setStartTime(frameIndex / 30.0); // For 30 fpsif (!transcoder->push(0, sample.get())) {
printError("Transcoder push", transcoder->error());
break;
}
}
// Flush remaining dataif (!transcoder->flush()) {
printError("Transcoder flush", transcoder->error());
}
transcoder->close();

Using Presets

AVBlocks provides presets for common encoding scenarios:

// Create output with preset nameauto outputSocket = primo::make_ref(Library::createMediaSocket("mp4.h264.aac"));
outputSocket->setFile(primo::ustring("output.mp4"));
// Or use specific presetauto outputSocket = primo::make_ref(Library::createMediaSocket("ipad.mp4.h264.576p"));
outputSocket->setFile(primo::ustring("output.mp4"));
// Add to transcoder
transcoder->outputs()->add(outputSocket.get());

Common presets:

  • MP4: mp4.h264.aac - H.264 video + AAC audio
  • iPad: ipad.mp4.h264.576p, ipad.mp4.h264.720p
  • iPhone: iphone.mp4.h264.480p
  • Android: android-phone.mp4.h264.360p, android-phone.mp4.h264.720p, android-tablet.mp4.h264.720p
  • DVD: dvd.pal.4x3.mp2, dvd.ntsc.16x9.mp2
  • WebM: webm.vp8.vorbis, android-tablet.webm.vp8.720p
  • Apple TV: appletv.h264.480p, appletv.h264.720p
  • VCD: vcd.pal, vcd.ntsc

Decoding Audio (Run Mode)

Decode AAC ADTS to raw PCM WAV:

// Create input socketauto inputSocket = primo::make_ref(Library::createMediaSocket());
inputSocket->setFile(primo::ustring("input.aac"));
// Create output socket for WAVauto outputSocket = primo::make_ref(Library::createMediaSocket());
outputSocket->setFile(primo::ustring("output.wav"));
outputSocket->setStreamType(StreamType::WAVE);
auto pin = primo::make_ref(Library::createMediaPin());
auto asi = primo::make_ref(Library::createAudioStreamInfo());
asi->setStreamType(StreamType::LPCM);
pin->setStreamInfo(asi.get());
outputSocket->pins()->add(pin.get());
// Setup and run transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (transcoder->open()) {
transcoder->run();
transcoder->close();
}

Decoding Audio (Pull Mode)

Decode AAC and extract decoded PCM samples:

// Setup input and output sockets// ...auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Pull decoded audio samplesint32_t outputIndex = 0;
auto sample = primo::make_ref(Library::createMediaSample());
while (transcoder->pull(outputIndex, sample.get())) {
// Process decoded audio
outfile.write((constchar*)sample->buffer()->data(),
sample->buffer()->dataSize());
}
const primo::error::ErrorInfo* error = transcoder->error();
if (error->facility() == primo::error::ErrorFacility::Codec &&
error->code() == primo::codecs::CodecError::EOS) {
// Success
}
transcoder->close();

Encoding Audio (Run Mode)

Encode WAV file to MP3:

// Input: WAV fileauto inputSocket = primo::make_ref(Library::createMediaSocket());
inputSocket->setFile(primo::ustring("input.wav"));
// Output: MP3auto outputSocket = primo::make_ref(Library::createMediaSocket());
outputSocket->setFile(primo::ustring("output.mp3"));
outputSocket->setStreamType(StreamType::MPEG_Audio);
outputSocket->setStreamSubType(StreamSubType::MPEG_Audio_Layer3);
auto pin = primo::make_ref(Library::createMediaPin());
auto asi = primo::make_ref(Library::createAudioStreamInfo());
asi->setStreamType(StreamType::MPEG_Audio);
asi->setStreamSubType(StreamSubType::MPEG_Audio_Layer3);
// Optional: set bitrate (default is 128000)// asi->setBitrate(192000);
pin->setStreamInfo(asi.get());
outputSocket->pins()->add(pin.get());
// Setup and run transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (transcoder->open()) {
transcoder->run();
transcoder->close();
}

Encoding Audio (Pull Mode)

Encode WAV to MP3 using pull mode:

// Setup input and output sockets// ...
std::ofstream outfile("output.mp3", std::ios::binary);
auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Pull encoded samplesint32_t outputIndex = 0;
auto sample = primo::make_ref(Library::createMediaSample());
while (transcoder->pull(outputIndex, sample.get())) {
outfile.write((constchar*)sample->buffer()->data(),
sample->buffer()->dataSize());
}
const primo::error::ErrorInfo* error = transcoder->error();
if (error->facility() == primo::error::ErrorFacility::Codec &&
error->code() == primo::codecs::CodecError::EOS) {
// Success
}
transcoder->close();

Encoding Audio (Push Mode)

Feed audio samples to encoder manually:

// Output socket for AAC/MP3// ...// Input socket without fileauto inputSocket = primo::make_ref(Library::createMediaSocket());
auto pin = primo::make_ref(Library::createMediaPin());
auto asi = primo::make_ref(Library::createAudioStreamInfo());
asi->setStreamType(StreamType::LPCM);
asi->setSampleRate(44100);
asi->setChannels(2);
asi->setBitsPerSample(16);
pin->setStreamInfo(asi.get());
inputSocket->pins()->add(pin.get());
auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Push audio samplesauto sample = primo::make_ref(Library::createMediaSample());
// Read audio data in chunkswhile (readAudioData(audioBuffer, bufferSize)) {
auto buffer = primo::make_ref(Library::createMediaBuffer(bufferSize));
memcpy(buffer->start(), audioBuffer, bufferSize);
buffer->setData(0, bufferSize);
sample->setBuffer(buffer.get());
if (!transcoder->push(0, sample.get())) {
break;
}
}
transcoder->flush();
transcoder->close();

Creating Video from Images

Create a video slideshow from a sequence of images:

// Use MediaInfo to get properties of first imageauto info = primo::make_ref(Library::createMediaInfo());
std::string firstImage = inputDir + "/image_0000.jpeg";
info->inputs()->at(0)->setFile(primo::ustring(firstImage));
if (!info->open()) {
returnfalse;
}
// Create input socket without file (we'll push images)auto inputSocket = primo::make_ref(Library::createMediaSocket());
auto pin = primo::make_ref(Library::createMediaPin());
// Clone video info from first image and set frame rateauto vsi = primo::make_ref(
(VideoStreamInfo*)info->outputs()->at(0)->pins()->at(0)->streamInfo()->clone()
);
vsi->setFrameRate(25.0); // 25 fps slideshow
pin->setStreamInfo(vsi.get());
inputSocket->pins()->add(pin.get());
// Create output socket with presetauto outputSocket = primo::make_ref(Library::createMediaSocket("mp4.h264.aac"));
outputSocket->setFile(primo::ustring("output.mp4"));
auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
returnfalse;
}
// Push imagesauto sample = primo::make_ref(Library::createMediaSample());
for (int i = 0; i < imageCount; i++) {
// Read image file into buffer
std::string imgFile = inputDir + "/image_" + std::to_string(i) + ".jpeg";
std::vector<uint8_t> imageData = readFileBytes(imgFile);
auto buffer = primo::make_ref(Library::createMediaBuffer());
buffer->attach(imageData.data(), imageData.size(), true);
sample->setBuffer(buffer.get());
// Set correct timestamp for video frame (required)
sample->setStartTime(i / 25.0);
if (!transcoder->push(0, sample.get())) {
break;
}
}
transcoder->flush();
transcoder->close();

Demuxing MP4 Container

Extract audio and video streams from MP4 container:

// Use MediaInfo to analyze inputauto info = primo::make_ref(Library::createMediaInfo());
info->inputs()->at(0)->setFile(primo::ustring("input.mp4"));
if (!info->open()) {
returnfalse;
}
// Find audio and video streamsint audioStreamIndex = -1;
int videoStreamIndex = -1;
MediaSocket* socket = info->outputs()->at(0);
for (int i = 0; i < socket->pins()->count(); i++) {
MediaPin* pin = socket->pins()->at(i);
if (pin->streamInfo()->mediaType() == MediaType::Audio) {
audioStreamIndex = i;
}
elseif (pin->streamInfo()->mediaType() == MediaType::Video) {
videoStreamIndex = i;
}
}
// Create input socketauto inputSocket = primo::make_ref(Library::createMediaSocket(info.get()));
// Create separate output sockets for audio and videoauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->inputs()->add(inputSocket.get());
if (videoStreamIndex >= 0) {
auto videoOutput = primo::make_ref(Library::createMediaSocket());
videoOutput->setFile(primo::ustring("video.mp4"));
videoOutput->setStreamType(StreamType::MP4);
auto videoPin = primo::make_ref(Library::createMediaPin());
videoPin->setStreamInfo(
socket->pins()->at(videoStreamIndex)->streamInfo()
);
videoOutput->pins()->add(videoPin.get());
transcoder->outputs()->add(videoOutput.get());
}
if (audioStreamIndex >= 0) {
auto audioOutput = primo::make_ref(Library::createMediaSocket());
audioOutput->setFile(primo::ustring("audio.mp4"));
audioOutput->setStreamType(StreamType::MP4);
auto audioPin = primo::make_ref(Library::createMediaPin());
audioPin->setStreamInfo(
socket->pins()->at(audioStreamIndex)->streamInfo()
);
audioOutput->pins()->add(audioPin.get());
transcoder->outputs()->add(audioOutput.get());
}
// Setup transcoder and process
transcoder->setAllowDemoMode(true);
if (transcoder->open()) {
transcoder->run();
transcoder->close();
}

Muxing Audio and Video into MP4

Combine separate audio and video streams into single MP4:

// Create first input for videoauto videoInput = primo::make_ref(Library::createMediaSocket());
videoInput->setFile(primo::ustring("video.mp4"));
// Create second input for audioauto audioInput = primo::make_ref(Library::createMediaSocket());
audioInput->setFile(primo::ustring("audio.mp4"));
// Create output socketauto outputSocket = primo::make_ref(Library::createMediaSocket());
outputSocket->setFile(primo::ustring("output.mp4"));
outputSocket->setStreamType(StreamType::MP4);
// Add both video and audio pins to outputauto videoPin = primo::make_ref(Library::createMediaPin());
auto vsi = primo::make_ref(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::H264);
videoPin->setStreamInfo(vsi.get());
outputSocket->pins()->add(videoPin.get());
auto audioPin = primo::make_ref(Library::createMediaPin());
auto asi = primo::make_ref(Library::createAudioStreamInfo());
asi->setStreamType(StreamType::AAC);
audioPin->setStreamInfo(asi.get());
outputSocket->pins()->add(audioPin.get());
// Setup transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(videoInput.get());
transcoder->inputs()->add(audioInput.get());
transcoder->outputs()->add(outputSocket.get());
if (transcoder->open()) {
transcoder->run();
transcoder->close();
}

Re-encoding Media

Take an MP4 input and re-encode the streams:

// Analyze inputauto info = primo::make_ref(Library::createMediaInfo());
info->inputs()->at(0)->setFile(primo::ustring("input.mp4"));
if (!info->open()) {
returnfalse;
}
// Create input socket from MediaInfoauto inputSocket = primo::make_ref(Library::createMediaSocket(info.get()));
// Create output socket with different encoding parametersauto outputSocket = primo::make_ref(Library::createMediaSocket("mp4.h264.aac"));
outputSocket->setFile(primo::ustring("output.mp4"));
// Optionally customize encoding parametersfor (int i = 0; i < outputSocket->pins()->count(); i++) {
MediaPin* pin = outputSocket->pins()->at(i);
if (pin->streamInfo()->mediaType() == MediaType::Video) {
VideoStreamInfo* vsi = static_cast<VideoStreamInfo*>(pin->streamInfo());
vsi->setBitrate(2000000); // 2 Mbps
vsi->setFrameRate(30.0);
}
elseif (pin->streamInfo()->mediaType() == MediaType::Audio) {
AudioStreamInfo* asi = static_cast<AudioStreamInfo*>(pin->streamInfo());
asi->setBitrate(128000); // 128 kbps
}
}
// Setup and run transcoderauto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (transcoder->open()) {
transcoder->run();
transcoder->close();
}

Decoding H.264 Access Units

Decode a stream of H.264 Access Units (AUs):

auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->setAllowDemoMode(true);
bool decoderInitialized = false;
int32_t index = 0;
for (int i = 0; ; i++) {
char auFile[PATH_MAX];
snprintf(auFile, PATH_MAX, "%s/au_%04d.h264", inputDir.c_str(), i);
if (!decoderInitialized) {
// Use MediaInfo on first AU to get stream propertiesauto info = primo::make_ref(Library::createMediaInfo());
info->inputs()->at(0)->setFile(primo::ustring(auFile));
if (!info->open()) {
returnfalse;
}
// Create input socket without file (will push data)auto inSocket = primo::make_ref(Library::createMediaSocket(info.get()));
inSocket->setFile(NULL);
inSocket->setStream(NULL);
// Create output socket for YUVauto outSocket = primo::make_ref(Library::createMediaSocket());
outSocket->setFile(primo::ustring("output.yuv"));
outSocket->setStreamType(StreamType::UncompressedVideo);
auto pin = primo::make_ref(Library::createMediaPin());
auto vsi = primo::make_ref(Library::createVideoStreamInfo());
vsi->setStreamType(StreamType::UncompressedVideo);
vsi->setColorFormat(ColorFormat::YUV420);
pin->setStreamInfo(vsi.get());
outSocket->pins()->add(pin.get());
transcoder->inputs()->add(inSocket.get());
transcoder->outputs()->add(outSocket.get());
if (!transcoder->open()) {
returnfalse;
}
decoderInitialized = true;
}
// Read AU data
std::vector<uint8_t> auData = readFileBytes(auFile);
if (auData.size() <= 0)
break;
// Push AU to decoderauto sample = primo::make_ref(Library::createMediaSample());
auto buffer = primo::make_ref(Library::createMediaBuffer());
buffer->attach(auData.data(), auData.size(), true);
sample->setBuffer(buffer.get());
if (!transcoder->push(index, sample.get())) {
printError("Transcoder push", transcoder->error());
returnfalse;
}
}
transcoder->flush();
transcoder->close();

Error Handling

Always check return values and handle errors properly:

auto transcoder = primo::make_ref(Library::createTranscoder());
transcoder->inputs()->add(inputSocket.get());
transcoder->outputs()->add(outputSocket.get());
if (!transcoder->open()) {
const primo::error::ErrorInfo* e = transcoder->error();
if (e->facility() == primo::error::ErrorFacility::Success) {
std::cout << "Success" << std::endl;
}
else {
if (e->message()) {
std::cout << "Error: " << primo::ustring(e->message()) << std::endl;
}
std::cout << "Facility: " << e->facility() << ", Code: " << e->code();
if (e->hint()) {
std::cout << ", Hint: " << primo::ustring(e->hint());
}
std::cout << std::endl;
}
returnfalse;
}
// For pull mode, check for end of streamwhile (transcoder->pull(outputIndex, sample.get())) {
// Process sample
}
const primo::error::ErrorInfo* error = transcoder->error();
if (error->facility() == primo::error::ErrorFacility::Codec &&
error->code() == primo::codecs::CodecError::EOS) {
// Successfully reached end of stream - this is normal
}
else {
// Actual error occurredprintError("Transcoder pull", error);
}

Memory Management

AVBlocks uses reference counting. Use primo::ref<> or primo::make_ref() smart pointers for automatic memory management:

// Using primo::ref with explicit constructor
primo::ref<Transcoder> transcoder(Library::createTranscoder());
// Automatically released when ref goes out of scope// Using primo::make_ref (C++11 style)auto socket = primo::make_ref(Library::createMediaSocket());
// Raw pointers are used when object ownership is managed elsewhere
MediaPin* pin = socket->pins()->at(0);
StreamInfo* si = pin->streamInfo();
// Don't delete raw pointers obtained from AVBlocks API// They are managed by their container objects

Platform-Specific Considerations

macOS

  • Link against libAVBlocks.dylib
  • Use primo::ustring for file paths to handle Unicode correctly

Linux

  • Link against libAVBlocks64.so
  • Ensure library path is in LD_LIBRARY_PATH or use rpath
  • Use primo::ustring for file paths to handle Unicode correctly

Windows

  • Link against AVBlocks64.lib (64-bit)
  • AVBlocks64.dll DLL must be in PATH or application directory
  • Use /MT or /MTd runtime library option

Examples

Complete working examples are available in the samples directory.

macOS

Getting Started

  • simple_converter — Transcode a media file using a Transcoder with hardcoded input and output file paths.

Media Info

Decoding Audio

Decoding Video

  • dec_avc_au — Decode a H.264 stream using sequence of files to simulate a stream of H.264 Access Units
  • dec_avc_file — Decode AVC/H.264 Annex B compressed file to YUV uncompressed file
  • dec_hevc_au — Decode an H.265 stream using sequence of files to simulate a stream of H.265 Access Units
  • dec_hevc_file — Decode an HEVC/H.265 Annex B compressed file to a raw uncompressed YUV video file
  • dec_vp8_file — Decode VP8 video in IVF container to YUV uncompressed file
  • dec_vp9_file — Decode VP9 video in IVF container to YUV uncompressed file

Encoding Audio

Encoding Video

  • enc_avc_file — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::run
  • enc_avc_pull — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::pull
  • enc_hevc_file — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::run
  • enc_hevc_pull — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::pull
  • enc_preset_file — Convert a raw YUV video file to a compressed video file using an AVBlocks preset
  • enc_vp8_file — Encode raw YUV video file to VP8 video in IVF container using Transcoder::run
  • enc_vp9_file — Encode raw YUV video file to VP9 video in IVF container using Transcoder::run

Muxing / Demuxing

  • demux_mp4_file — Extract the first audio and video elementary stream from an MP4 container into separate MP4 files
  • demux_webm_file — Extract the first audio and video elementary stream from a WebM container into separate WebM files
  • dump_avc_au — Split an H.264 (AVC) elementary stream to access units (AU), writing each to a separate file
  • dump_hevc_au — Split an H.265 (HEVC) elementary stream into access units (AU), writing each to a separate file
  • mux_mp4_file — Multiplex two single-stream MP4 files (AAC audio + H.264 video) into an MP4 container
  • mux_webm_file — Multiplex two single-stream WebM files (Vorbis audio + VP8 video) into a WebM container

Advanced

  • re-encode — Take an MP4 input and re-encode audio and video streams back into MP4 output
  • slideshow — Create a video clip from a sequence of images

Audio Processing

Video Processing

  • video_framerate — Change the frame rate of a video from 24 fps to 30 fps
  • video_pad — Add black border padding around a video
  • video_crop — Crop a video by removing pixels from the edges
  • video_upscale — Upscale a video to Full HD (1920×1080) using bicubic interpolation

Linux

Getting Started

  • simple_converter — Transcode a media file using a Transcoder with hardcoded input and output file paths.

Media Info

Decoding Audio

Decoding Video

  • dec_avc_au — Decode a H.264 stream using sequence of files to simulate a stream of H.264 Access Units
  • dec_avc_file — Decode AVC/H.264 Annex B compressed file to YUV uncompressed file
  • dec_hevc_au — Decode an H.265 stream using sequence of files to simulate a stream of H.265 Access Units
  • dec_hevc_file — Decode an HEVC/H.265 Annex B compressed file to a raw uncompressed YUV video file
  • dec_vp8_file — Decode VP8 video in IVF container to YUV uncompressed file
  • dec_vp9_file — Decode VP9 video in IVF container to YUV uncompressed file

Encoding Audio

Encoding Video

  • enc_avc_file — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::run
  • enc_avc_pull — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::pull
  • enc_hevc_file — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::run
  • enc_hevc_pull — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::pull
  • enc_preset_file — Convert a raw YUV video file to a compressed video file using an AVBlocks preset
  • enc_vp8_file — Encode raw YUV video file to VP8 video in IVF container using Transcoder::run
  • enc_vp9_file — Encode raw YUV video file to VP9 video in IVF container using Transcoder::run

Muxing / Demuxing

  • demux_mp4_file — Extract the first audio and video elementary stream from an MP4 container into separate MP4 files
  • demux_webm_file — Extract the first audio and video elementary stream from a WebM container into separate WebM files
  • dump_avc_au — Split an H.264 (AVC) elementary stream to access units (AU), writing each to a separate file
  • dump_hevc_au — Split an H.265 (HEVC) elementary stream into access units (AU), writing each to a separate file
  • mux_mp4_file — Multiplex two single-stream MP4 files (AAC audio + H.264 video) into an MP4 container
  • mux_webm_file — Multiplex two single-stream WebM files (Vorbis audio + VP8 video) into a WebM container

Advanced

  • re-encode — Take an MP4 input and re-encode audio and video streams back into MP4 output
  • slideshow — Create a video clip from a sequence of images

Audio Processing

Video Processing

  • video_framerate — Change the frame rate of a video from 24 fps to 30 fps
  • video_pad — Add black border padding around a video
  • video_crop — Crop a video by removing pixels from the edges
  • video_upscale — Upscale a video to Full HD (1920×1080) using bicubic interpolation

Windows

Getting Started

  • simple_converter — Transcode a media file using a Transcoder with hardcoded input and output file paths.

Media Info

Decoding Audio

Decoding Video

  • dec_avc_au — Decode a H.264 stream using sequence of files to simulate a stream of H.264 Access Units
  • dec_avc_file — Decode AVC/H.264 Annex B compressed file to YUV uncompressed file
  • dec_hevc_au — Decode an H.265 stream using sequence of files to simulate a stream of H.265 Access Units
  • dec_hevc_file — Decode an HEVC/H.265 Annex B compressed file to a raw uncompressed YUV video file
  • dec_vp8_file — Decode VP8 video in IVF container to YUV uncompressed file
  • dec_vp9_file — Decode VP9 video in IVF container to YUV uncompressed file

Encoding Audio

Encoding Video

  • enc_avc_file — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::run
  • enc_avc_pull — Encode raw YUV video file to AVC/H.264 Annex B video file using Transcoder::pull
  • enc_hevc_file — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::run
  • enc_hevc_pull — Encode raw YUV video file to HEVC/H.265 Annex B video file using Transcoder::pull
  • enc_preset_file — Convert a raw YUV video file to a compressed video file using an AVBlocks preset
  • enc_vp8_file — Encode raw YUV video file to VP8 video in IVF container using Transcoder::run
  • enc_vp9_file — Encode raw YUV video file to VP9 video in IVF container using Transcoder::run

Muxing / Demuxing

  • demux_mp4_file — Extract the first audio and video elementary stream from an MP4 container into separate MP4 files
  • demux_webm_file — Extract the first audio and video elementary stream from a WebM container into separate WebM files
  • dump_avc_au — Split an H.264 (AVC) elementary stream to access units (AU), writing each to a separate file
  • dump_hevc_au — Split an H.265 (HEVC) elementary stream into access units (AU), writing each to a separate file
  • mux_mp4_file — Multiplex two single-stream MP4 files (AAC audio + H.264 video) into an MP4 container
  • mux_webm_file — Multiplex two single-stream WebM files (Vorbis audio + VP8 video) into a WebM container

Advanced

  • re-encode — Take an MP4 input and re-encode audio and video streams back into MP4 output
  • slideshow — Create a video clip from a sequence of images

Audio Processing

Video Processing

  • video_framerate — Change the frame rate of a video from 24 fps to 30 fps
  • video_pad — Add black border padding around a video
  • video_crop — Crop a video by removing pixels from the edges
  • video_upscale — Upscale a video to Full HD (1920×1080) using bicubic interpolation

Development

macOS

Download AVBlocks Core and Assets

See Download Core and Assets on macOS

Setup

See Setup for macOS

Build

See Build on macOS

Run

See README in the samples subdirectory.

Linux

Download AVBlocks Core and Assets

See Download Core and Assets on Linux

Setup

See Setup for Linux

Build

See Build on Linux

Run

See README in the samples subdirectory.

Windows

Download AVBlocks Core and Assets

See Download Core and Assets on Windows

Setup

See Setup for Windows

Build

See Build on Windows

Run

See README in the samples subdirectory.

How to obtain Commercial License

See License Options for details.

We offer discounts for:

  • Competitive product
  • Startup
  • Educational institution
  • Open source project

Used by

Contributors

Languages