Last active
October 26, 2019 07:50
-
-
Save irieger/604125fba000f76095626696f34ae619 to your computer and use it in GitHub Desktop.
Excerpt of my try to use libavformat to pack (mov) movie containers with external CFHD frame encoding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::string filename; | |
AVFormatContext* format_context = NULL; | |
int32_t out_height = 1080; | |
int32_t out_width = 1920; | |
int32_t out_framerate = 24; | |
AVOutputFormat* out_format = nullptr; | |
AVStream* out_avstream = nullptr; | |
int error; | |
error = avformat_alloc_output_context2(&format_context, NULL, NULL, filename.c_str()); | |
if (error != 0) | |
{ | |
std::cerr << "Unable to create output context" << std::endl; | |
std::exit(1); | |
} | |
out_format = clip->_format_context->oformat; | |
out_format->video_codec = AV_CODEC_ID_CFHD; | |
num_frames = 0; | |
out_avstream = avformat_new_stream(format_context, NULL); | |
if (clip->_out_avstream == NULL) | |
{ | |
std::cerr << "Unable to create output video stream" << std::endl; | |
std::exit(1); | |
} | |
out_avstream->time_base = (AVRational){1, 24}; | |
out_avstream->avg_frame_rate = (AVRational){24, 1}; | |
// clip->_out_avstream->time_base.num = 1; | |
// clip->_out_avstream->time_base.den = 12288; | |
// clip->_out_avstream->avg_frame_rate.num = 24; | |
// clip->_out_avstream->avg_frame_rate.den = 1; | |
out_avstream->r_frame_rate = clip->_out_avstream->avg_frame_rate; | |
out_avstream->codec->time_base = clip->_out_avstream->time_base; | |
AVCodecParameters* codecpar = out_avstream->codecpar; | |
codecpar->codec_type = AVMEDIA_TYPE_VIDEO; | |
codecpar->codec_id = AV_CODEC_ID_CFHD; | |
codecpar->codec_tag = 1145587267; | |
codecpar->extradata_size = 0; | |
switch (mode) | |
{ | |
case CineformMode::YUV422: | |
codecpar->format = 66; | |
break; | |
default: | |
codecpar->format = 137; // RGB | |
} | |
codecpar->bit_rate = 61389834; //! @todo Correct bitrate information?! | |
codecpar->bits_per_coded_sample = 24; | |
codecpar->bits_per_raw_sample = 10; | |
codecpar->profile = -99; | |
codecpar->level = -99; | |
codecpar->width = width; | |
codecpar->height = height; | |
codecpar->sample_aspect_ratio.num = 0; | |
codecpar->sample_aspect_ratio.den = 1; | |
codecpar->field_order = AV_FIELD_PROGRESSIVE; | |
codecpar->color_range = AVCOL_RANGE_UNSPECIFIED; | |
codecpar->color_primaries = AVCOL_PRI_UNSPECIFIED; | |
codecpar->color_trc = AVCOL_TRC_UNSPECIFIED; | |
codecpar->color_space = AVCOL_SPC_UNSPECIFIED; | |
codecpar->chroma_location = AVCHROMA_LOC_UNSPECIFIED; | |
codecpar->video_delay = 0; | |
codecpar->channel_layout = 0; | |
codecpar->channels = 0; | |
codecpar->sample_rate = 0; | |
codecpar->block_align = 0; | |
codecpar->frame_size = 0; | |
codecpar->initial_padding = 0; | |
codecpar->trailing_padding = 0; | |
codecpar->seek_preroll = 0; | |
av_dump_format(format_context, 0, filename.c_str(), 1); | |
error = avio_open(&format_context->pb, filename.c_str(), AVIO_FLAG_WRITE); | |
if (error < 0) | |
{ | |
std::cerr << "Unable to create output file" << std::endl; | |
std::exit(1); | |
} | |
error = avformat_write_header(format_context, NULL); | |
if (error < 0) | |
{ | |
std::cerr << "Unable to write header" << std::endl; | |
std::exit(1); | |
} | |
for all frames | |
{ | |
int frame // number of the current frame | |
uint16_t* img_data // is filled with the data for the current frame | |
void* frame_data; // will contain the compressed data returned by cineformsdk | |
size_t frame_data_size; // size of frame_data | |
// cfhd_handler is a wrapper class that encapsulates the cineformSDK | |
if (cfhd_handler->encodeCfhdFrame(&frame_data, frame_data_size, img_data, | |
out_height, out_width, frame)) | |
{ | |
std::cout << "Frame compressed. Frame: " << frame << ", compressed_size: " << frame_data_size << std::endl; | |
} | |
else | |
{ | |
std::cerr << "Failed to compress frame" << std::endl; | |
std::exit(1); | |
} | |
AVRational tc; | |
tc.num = frame; | |
tc.den = out_framerate; | |
AVPacket pkg; | |
pkg.buf = NULL; | |
pkg.pts = frame; | |
pkg.dts = frame; | |
pkg.data = reinterpret_cast<uint8_t*>(frame_data); | |
pkg.size = frame_data_size; | |
pkg.stream_index = out_avstream->index; | |
pkg.flags = 0; | |
pkg.side_data = NULL; | |
pkg.side_data_elems = 0; | |
pkg.duration = 0; | |
pkg.pos = -1; | |
error = av_interleaved_write_frame(format_context, &pkg); | |
if (error < 0) | |
{ | |
std::cerr << "Unable to write frame to stream" << std::endl; | |
std::exit(1); | |
} | |
num_frames++; | |
} | |
av_write_trailer(format_context); | |
avio_closep(&format_context->pb); | |
avformat_free_context(format_context); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
..$ ffmpeg -i testinput.mov | |
ffmpeg version 4.2.1-0york0~18.04.1 Copyright (c) 2000-2019 the FFmpeg developers | |
built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1) | |
configuration: --prefix=/usr --extra-version='0york0~18.04.1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-nonfree --enable-libfdk-aac --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared | |
libavutil 56. 31.100 / 56. 31.100 | |
libavcodec 58. 54.100 / 58. 54.100 | |
libavformat 58. 29.100 / 58. 29.100 | |
libavdevice 58. 8.100 / 58. 8.100 | |
libavfilter 7. 57.100 / 7. 57.100 | |
libavresample 4. 0. 0 / 4. 0. 0 | |
libswscale 5. 5.100 / 5. 5.100 | |
libswresample 3. 5.100 / 3. 5.100 | |
libpostproc 55. 5.100 / 55. 5.100 | |
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cineform_burnin.mov': | |
Metadata: | |
major_brand : qt | |
minor_version : 512 | |
compatible_brands: qt | |
encoder : Lavf57.25.100 | |
Duration: 00:01:07.33, start: 0.000000, bitrate: 287108 kb/s | |
Stream #0:0(eng): Video: cfhd (CFHD / 0x44484643), gbrp12le(10 bpc, bt709, progressive), 1920x1080, 287106 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 12288 tbn, 12288 tbc (default) | |
Metadata: | |
handler_name : VideoHandler | |
encoder : GoPro CineForm RGB 16-bit | |
timecode : 01:00:00:00 | |
Stream #0:1(eng): Data: none (tmcd / 0x64636D74) | |
Metadata: | |
handler_name : TimeCodeHandler | |
timecode : 01:00:00:00 | |
At least one output file must be specified | |
================================================ | |
..$ ffmpeg -i testoutput.mov | |
ffmpeg version 4.2.1-0york0~18.04.1 Copyright (c) 2000-2019 the FFmpeg developers | |
built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1) | |
configuration: --prefix=/usr --extra-version='0york0~18.04.1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-nonfree --enable-libfdk-aac --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared | |
libavutil 56. 31.100 / 56. 31.100 | |
libavcodec 58. 54.100 / 58. 54.100 | |
libavformat 58. 29.100 / 58. 29.100 | |
libavdevice 58. 8.100 / 58. 8.100 | |
libavfilter 7. 57.100 / 7. 57.100 | |
libavresample 4. 0. 0 / 4. 0. 0 | |
libswscale 5. 5.100 / 5. 5.100 | |
libswresample 3. 5.100 / 3. 5.100 | |
libpostproc 55. 5.100 / 55. 5.100 | |
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testout.mov': | |
Metadata: | |
major_brand : qt | |
minor_version : 512 | |
compatible_brands: qt | |
encoder : Lavf58.29.100 | |
Duration: 00:00:00.04, start: 0.000000, bitrate: 817533 kb/s | |
Stream #0:0: Video: cfhd (CFHD / 0x44484643), gbrp12le(10 bpc, progressive), 1920x1080, 817538 kb/s, 119.07 fps, 12288 tbr, 12288 tbn, 12288 tbc (default) | |
Metadata: | |
handler_name : VideoHandler | |
At least one output file must be specified |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment