Compare commits
10 commits
41c291f51c
...
49071365f7
Author | SHA1 | Date | |
---|---|---|---|
49071365f7 | |||
00703f8299 | |||
f17539ac14 | |||
d551c9da3b | |||
1d27fd3b21 | |||
2e03098540 | |||
1c3554b3ca | |||
c1c271b77e | |||
379fb4cadf | |||
d429cf44ff |
7 changed files with 73 additions and 30 deletions
|
@ -40,3 +40,6 @@ target_link_libraries(DitheringProject PUBLIC
|
||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
${FFMPEG_LIBAVCODEC_LINK_LIBRARIES}
|
${FFMPEG_LIBAVCODEC_LINK_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(DitheringProject PRIVATE
|
||||||
|
CL_TARGET_OPENCL_VERSION=300)
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2021 Stephen Seo
|
Copyright (c) 2021-2024 Stephen Seo
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
of the course. Newer versions are meant to be maintenance releases; fixes that
|
of the course. Newer versions are meant to be maintenance releases; fixes that
|
||||||
keep the project working. As of 2022-01-18, there may be (after now) a version
|
keep the project working. As of 2022-01-18, there may be (after now) a version
|
||||||
`1.1.0` or `1.0.1` due to keeping up to date with the FFmpeg dependency as a new
|
`1.1.0` or `1.0.1` due to keeping up to date with the FFmpeg dependency as a new
|
||||||
major version of FFmpeg was released (version `5.0`).
|
major version of FFmpeg was released (version `5.0`).~~
|
||||||
|
|
||||||
To be clear, version `1.0.0` of this project is expected to work with FFmpeg
|
~~To be clear, version `1.0.0` of this project is expected to work with FFmpeg
|
||||||
version `4.4`.~~
|
version `4.4`.~~
|
||||||
|
|
||||||
Fixes were applied for FFmpeg version 5. A macro is used to change incompatible
|
Fixes were applied for FFmpeg version 5. A macro is used to change incompatible
|
||||||
|
|
|
@ -7,6 +7,7 @@ Args::Args()
|
||||||
: do_dither_image_(true),
|
: do_dither_image_(true),
|
||||||
do_dither_grayscaled_(false),
|
do_dither_grayscaled_(false),
|
||||||
do_overwrite_(false),
|
do_overwrite_(false),
|
||||||
|
do_video_pngs_(false),
|
||||||
input_filename(),
|
input_filename(),
|
||||||
output_filename() {}
|
output_filename() {}
|
||||||
|
|
||||||
|
|
|
@ -694,34 +694,60 @@ OpenCLContext::OpenCLContext() : context_(nullptr), queue_(nullptr) {
|
||||||
//////////////////// set up cl_context
|
//////////////////// set up cl_context
|
||||||
cl_int err_num;
|
cl_int err_num;
|
||||||
cl_uint num_platforms;
|
cl_uint num_platforms;
|
||||||
cl_platform_id first_platform_id;
|
std::vector<cl_platform_id> platform_ids;
|
||||||
|
|
||||||
err_num = clGetPlatformIDs(1, &first_platform_id, &num_platforms);
|
err_num = clGetPlatformIDs(0, nullptr, &num_platforms);
|
||||||
if (err_num != CL_SUCCESS || num_platforms == 0) {
|
if (err_num != CL_SUCCESS) {
|
||||||
|
std::cout << "ERROR: OpenCLContext: Failed to query OpenCL platforms"
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
} else if (num_platforms == 0) {
|
||||||
std::cout << "ERROR: OpenCLContext: Failed to find any OpenCL platforms"
|
std::cout << "ERROR: OpenCLContext: Failed to find any OpenCL platforms"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl_context_properties context_properties[] = {
|
platform_ids.resize(num_platforms);
|
||||||
CL_CONTEXT_PLATFORM,
|
|
||||||
reinterpret_cast<cl_context_properties>(first_platform_id), 0};
|
|
||||||
|
|
||||||
context_ = clCreateContextFromType(context_properties, CL_DEVICE_TYPE_GPU,
|
|
||||||
nullptr, nullptr, &err_num);
|
|
||||||
|
|
||||||
|
err_num = clGetPlatformIDs(num_platforms, platform_ids.data(), nullptr);
|
||||||
if (err_num != CL_SUCCESS) {
|
if (err_num != CL_SUCCESS) {
|
||||||
std::cout << "ERROR: OpenCLContext: Failed to create GPU context, "
|
std::cout << "ERROR: OpenCLContext: Failed to get OpenCL platform id(s)"
|
||||||
<< "trying CPU..." << std::endl;
|
<< std::endl;
|
||||||
context_ = clCreateContextFromType(context_properties, CL_DEVICE_TYPE_CPU,
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
for (cl_uint i = 0; i < num_platforms; ++i) {
|
||||||
|
cl_context_properties context_properties[] = {
|
||||||
|
CL_CONTEXT_PLATFORM,
|
||||||
|
reinterpret_cast<cl_context_properties>(platform_ids[i]), 0};
|
||||||
|
|
||||||
|
context_ = clCreateContextFromType(context_properties, CL_DEVICE_TYPE_GPU,
|
||||||
nullptr, nullptr, &err_num);
|
nullptr, nullptr, &err_num);
|
||||||
|
|
||||||
if (err_num != CL_SUCCESS) {
|
if (err_num != CL_SUCCESS) {
|
||||||
std::cout << "ERROR: OpenCLContext: Failed to create CPU context"
|
std::cout << "ERROR: OpenCLContext: Failed to create GPU context, "
|
||||||
<< std::endl;
|
<< "trying CPU..." << std::endl;
|
||||||
context_ = nullptr;
|
context_ = clCreateContextFromType(context_properties, CL_DEVICE_TYPE_CPU,
|
||||||
return;
|
nullptr, nullptr, &err_num);
|
||||||
|
if (err_num != CL_SUCCESS) {
|
||||||
|
std::cout << "ERROR: OpenCLContext: Failed to create CPU context"
|
||||||
|
<< std::endl;
|
||||||
|
context_ = nullptr;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!success) {
|
||||||
|
std::cout << "ERROR: OpenCLContext: Failed to find a valid OpenCL context!"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
//////////////////// end set up cl context
|
//////////////////// end set up cl context
|
||||||
|
|
||||||
//////////////////// set up command queue
|
//////////////////// set up command queue
|
||||||
|
@ -754,7 +780,8 @@ OpenCLContext::OpenCLContext() : context_(nullptr), queue_(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// uses first available device
|
// uses first available device
|
||||||
queue_ = clCreateCommandQueue(context_, devices.at(0), 0, &err_num);
|
queue_ = clCreateCommandQueueWithProperties(context_, devices.at(0), nullptr,
|
||||||
|
&err_num);
|
||||||
if (err_num != CL_SUCCESS) {
|
if (err_num != CL_SUCCESS) {
|
||||||
std::cout << "ERROR: OpenCLContext: Failed to create command queue"
|
std::cout << "ERROR: OpenCLContext: Failed to create command queue"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
24
src/video.cc
24
src/video.cc
|
@ -265,7 +265,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
return_value = avcodec_open2(enc_codec_context, enc_codec, nullptr);
|
return_value = avcodec_open2(enc_codec_context, enc_codec, nullptr);
|
||||||
if (return_value != 0) {
|
if (return_value != 0) {
|
||||||
std::cout << "ERROR: Failed to init enc_codec_context" << std::endl;
|
std::cout << "ERROR: Failed to init enc_codec_context" << std::endl;
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -279,7 +279,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
if (return_value < 0) {
|
if (return_value < 0) {
|
||||||
std::cout << "ERROR: Failed to set encoding codec parameters in stream"
|
std::cout << "ERROR: Failed to set encoding codec parameters in stream"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -298,7 +298,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
if (return_value < 0) {
|
if (return_value < 0) {
|
||||||
std::cout << "ERROR: Failed to open file \"" << output_filename
|
std::cout << "ERROR: Failed to open file \"" << output_filename
|
||||||
<< "\" for writing" << std::endl;
|
<< "\" for writing" << std::endl;
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -313,7 +313,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
if (return_value < 0) {
|
if (return_value < 0) {
|
||||||
std::cout << "ERROR: Failed to write header in output video file"
|
std::cout << "ERROR: Failed to write header in output video file"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -332,7 +332,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
HandleDecodingPacket(codec_ctx, pkt, frame, blue_noise, grayscale,
|
HandleDecodingPacket(codec_ctx, pkt, frame, blue_noise, grayscale,
|
||||||
color_changed, output_as_pngs);
|
color_changed, output_as_pngs);
|
||||||
if (!std::get<0>(ret_tuple)) {
|
if (!std::get<0>(ret_tuple)) {
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_unref(pkt);
|
av_packet_unref(pkt);
|
||||||
|
@ -345,7 +345,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context,
|
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context,
|
||||||
yuv_frame, enc_stream)) {
|
yuv_frame, enc_stream)) {
|
||||||
av_frame_free(&yuv_frame);
|
av_frame_free(&yuv_frame);
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_unref(pkt);
|
av_packet_unref(pkt);
|
||||||
|
@ -366,7 +366,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
HandleDecodingPacket(codec_ctx, nullptr, frame, blue_noise, grayscale,
|
HandleDecodingPacket(codec_ctx, nullptr, frame, blue_noise, grayscale,
|
||||||
color_changed, output_as_pngs);
|
color_changed, output_as_pngs);
|
||||||
if (!std::get<0>(ret_tuple)) {
|
if (!std::get<0>(ret_tuple)) {
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -378,7 +378,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context, yuv_frame,
|
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context, yuv_frame,
|
||||||
enc_stream)) {
|
enc_stream)) {
|
||||||
av_frame_free(&yuv_frame);
|
av_frame_free(&yuv_frame);
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -394,7 +394,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
// flush encoder
|
// flush encoder
|
||||||
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context, nullptr,
|
if (!HandleEncodingFrame(avf_enc_context, enc_codec_context, nullptr,
|
||||||
enc_stream)) {
|
enc_stream)) {
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
avformat_free_context(avf_enc_context);
|
avformat_free_context(avf_enc_context);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
@ -409,7 +409,7 @@ bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
if (enc_codec_context) {
|
if (enc_codec_context) {
|
||||||
avcodec_close(enc_codec_context);
|
IGPUP_DITHERING_avcodec_close_ctx(&enc_codec_context);
|
||||||
}
|
}
|
||||||
if (!output_as_pngs && !(avf_enc_context->oformat->flags & AVFMT_NOFILE)) {
|
if (!output_as_pngs && !(avf_enc_context->oformat->flags & AVFMT_NOFILE)) {
|
||||||
avio_closep(&avf_enc_context->pb);
|
avio_closep(&avf_enc_context->pb);
|
||||||
|
@ -614,7 +614,11 @@ std::tuple<bool, std::vector<AVFrame *>> Video::HandleDecodingPacket(
|
||||||
// cleanup
|
// cleanup
|
||||||
av_frame_free(&temp_frame);
|
av_frame_free(&temp_frame);
|
||||||
yuv_frame->pts = frame_count_ - 1;
|
yuv_frame->pts = frame_count_ - 1;
|
||||||
|
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(58, 2, 100)
|
||||||
yuv_frame->pkt_duration = 1;
|
yuv_frame->pkt_duration = 1;
|
||||||
|
#else
|
||||||
|
yuv_frame->duration = 1;
|
||||||
|
#endif
|
||||||
return_frames.push_back(yuv_frame);
|
return_frames.push_back(yuv_frame);
|
||||||
} // else (!output_as_pngs)
|
} // else (!output_as_pngs)
|
||||||
} // while (return_value >= 0)
|
} // while (return_value >= 0)
|
||||||
|
|
|
@ -11,6 +11,14 @@ extern "C" {
|
||||||
|
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
|
inline void IGPUP_DITHERING_avcodec_close_ctx(AVCodecContext **avctx) {
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 3, 100)
|
||||||
|
avcodec_free_context(avctx);
|
||||||
|
#else
|
||||||
|
avcodec_close(*avctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
constexpr unsigned int kReadBufSize = 4096;
|
constexpr unsigned int kReadBufSize = 4096;
|
||||||
constexpr unsigned int kReadBufPaddingSize = AV_INPUT_BUFFER_PADDING_SIZE;
|
constexpr unsigned int kReadBufPaddingSize = AV_INPUT_BUFFER_PADDING_SIZE;
|
||||||
constexpr unsigned int kReadBufSizeWithPadding =
|
constexpr unsigned int kReadBufSizeWithPadding =
|
||||||
|
|
Loading…
Reference in a new issue