HEVC / H.265 Annex B Encoder (Run)¶
This article explains how to use TTranscoder::run to encode a raw YUV video file to HEVC / H.265 Annex B elementary stream format.
The code snippets are from the enc_hevc_file macOS sample.
Linux and Windows samples are also available:
Source Video¶
The sample uses foreman_qcif.yuv from the AVBlocks Assets repository. After downloading and unzipping the assets, the file is in the vid subdirectory.
Code¶
Initialize AVBlocks¶
Initialize the library before using AVBlocks and shut it down when encoding is complete.
int main(int argc, char* argv[])
{
Options opt;
switch(prepareOptions(opt, argc, argv))
{
case Command: return 0;
case Error: return 1;
case Parsed: break;
}
TLibrary library;
return encode(opt) ? 0 : 1;
}
Configure Input Socket¶
The input socket describes the raw YUV file. Its dimensions, frame rate, and color format must match the source file.
TMediaSocket()
.file(opt.yuv_file)
.streamType(StreamType::UncompressedVideo)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::UncompressedVideo)
.frameWidth(opt.frame_size.width_)
.frameHeight(opt.frame_size.height_)
.colorFormat(opt.yuv_color.Id)
.frameRate(opt.fps)
.scanType(ScanType::Progressive)
)
)
Configure Output Socket¶
Set the output stream type to H265 and the subtype to HEVC_Annex_B to produce an elementary HEVC stream.
TMediaSocket()
.file(opt.h265_file)
.streamType(StreamType::H265)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::H265)
.streamSubType(StreamSubType::HEVC_Annex_B)
)
)
Configure Transcoder and Encode¶
Create the sockets, enable demo mode, add the sockets to a transcoder, and run it. The sample removes an existing output because the transcoder intentionally fails when the output file already exists.
bool encode(const Options& opt)
{
try {
deleteFile(opt.h265_file.c_str());
TTranscoder()
.allowDemoMode(true)
.addInput(
TMediaSocket()
.file(opt.yuv_file)
.streamType(StreamType::UncompressedVideo)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::UncompressedVideo)
.frameWidth(opt.frame_size.width_)
.frameHeight(opt.frame_size.height_)
.colorFormat(opt.yuv_color.Id)
.frameRate(opt.fps)
.scanType(ScanType::Progressive)
)
)
)
.addOutput(
TMediaSocket()
.file(opt.h265_file)
.streamType(StreamType::H265)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::H265)
.streamSubType(StreamSubType::HEVC_Annex_B)
)
)
)
.open()
.run()
.close();
std::println("Output: {}", opt.h265_file);
return true;
} catch (const TAVBlocksException& ex) {
std::println(stderr, "AVBlocks error: {}", ex.what());
return false;
} catch (const std::exception& ex) {
std::println(stderr, "Error: {}", ex.what());
return false;
}
}
Complete C++ Code¶
Here’s the complete working example from enc_hevc_file.cpp:
#include <primo/avblocks/avb++.h>
#include <print>
#include "options.h"
#include "util.h"
using namespace primo::codecs;
using namespace primo::avblocks::modern;
bool encode(const Options& opt)
{
try {
deleteFile(opt.h265_file.c_str());
TTranscoder()
.allowDemoMode(true)
.addInput(
TMediaSocket()
.file(opt.yuv_file)
.streamType(StreamType::UncompressedVideo)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::UncompressedVideo)
.frameWidth(opt.frame_size.width_)
.frameHeight(opt.frame_size.height_)
.colorFormat(opt.yuv_color.Id)
.frameRate(opt.fps)
.scanType(ScanType::Progressive)
)
)
)
.addOutput(
TMediaSocket()
.file(opt.h265_file)
.streamType(StreamType::H265)
.addPin(
TMediaPin()
.streamInfo(TVideoStreamInfo()
.streamType(StreamType::H265)
.streamSubType(StreamSubType::HEVC_Annex_B)
)
)
)
.open()
.run()
.close();
std::println("Output: {}", opt.h265_file);
return true;
} catch (const TAVBlocksException& ex) {
std::println(stderr, "AVBlocks error: {}", ex.what());
return false;
} catch (const std::exception& ex) {
std::println(stderr, "Error: {}", ex.what());
return false;
}
}
int main(int argc, char* argv[])
{
Options opt;
switch(prepareOptions(opt, argc, argv))
{
case Command: return 0;
case Error: return 1;
case Parsed: break;
}
TLibrary library;
return encode(opt) ? 0 : 1;
}
How to Run¶
See the build instructions and the enc_hevc_file macOS sample for details.
Command Line¶
./enc_hevc_file --frame <width>x<height> --rate <fps> --color <COLOR> --input <file.yuv> --output <file.h265> [--colors] [--help]
Examples¶
List options:
./bin/x64/enc_hevc_file --help
enc_hevc_file --frame <width>x<height> --rate <fps> --color <COLOR> --input <file.yuv> --output <file.h265> [--colors]
-h, --help
-i, --input input YUV file
-o, --output output H265 file
-r, --rate input frame rate
-f, --frame input frame sizes <width>x<height>
-c, --color input color format. Use --colors to list all supported color
formats
--colors list COLOR constants
Encode the QCIF source to an HEVC file:
mkdir -p ./output/enc_hevc_file
./bin/x64/enc_hevc_file \
--input ./assets/vid/foreman_qcif.yuv \
--output ./output/enc_hevc_file/foreman_qcif.h265 \
--frame 176x144 \
--rate 30 \
--color yuv420