Skip to content

Commit

Permalink
Added support to crop vodeo from top and bottom.
Browse files Browse the repository at this point in the history
by default, extend vidoe to PAL/NTSC lines count with black lines
  • Loading branch information
shiloxyz authored and shiloxyz committed Jun 16, 2020
1 parent ffa3b3d commit 03f90ac
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 127 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ pcm_coder -c <название кодека ffmpeg> -b <битрейт виде
## TODO

* [_] Поддержка 16 бит (--16)
* [_] Поддержка обрезки (--Cut)
* [v] Поддержка обрезки (--Cut) - Заменено на произвольную обрезку сверху и снизу --crop-*
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ set(SRC
ipcmframeprocessingpolicy.h
iframe.h

pixeldublicator.h
pixeldublicator.cpp
frameextender.h
frameextender.cpp
)

if (USE_PLAYER)
Expand Down
10 changes: 7 additions & 3 deletions src/ffmpegvideocoder.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#include <cstring>

#include "frame.h"

#include "WriteContext.h"

#include "ffmpegvideocoder.h"

FFmpegVideoCoder::FFmpegVideoCoder(const std::string &filename,
const std::string &codec,
const uint32_t bitrate, bool PAL, bool cut)
: filename{filename}, codec{codec}, bitrate{bitrate}, PAL{PAL}, cut{cut} {}
const uint32_t bitrate, bool PAL)
: filename{filename}, codec{codec}, bitrate{bitrate}, PAL{PAL} {}

FFmpegVideoCoder::~FFmpegVideoCoder() {}

Expand All @@ -14,7 +18,7 @@ void FFmpegVideoCoder::Init(size_t width, size_t heigth) {
this->heigth = heigth;

encoder = std::make_unique<FfmpegWriteContext>(
filename, codec, heigth, PIXEL_WIDTH, bitrate, PAL, width);
filename, codec, this->heigth, PIXEL_WIDTH, bitrate, PAL, width);
}

void FFmpegVideoCoder::operator()(std::unique_ptr<IFrame> &frame) {
Expand Down
4 changes: 1 addition & 3 deletions src/ffmpegvideocoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ struct FFmpegVideoCoder : public IPCMFrameProcessingPolicy {
static constexpr auto PIXEL_WIDTH = 720;

FFmpegVideoCoder(const std::string &filename, const std::string &codec,
const uint32_t bitrate = -1, bool PAL = true,
bool cut = false);
const uint32_t bitrate = -1, bool PAL = true);
~FFmpegVideoCoder();

void Init(size_t width, size_t heigth) override;
Expand All @@ -28,7 +27,6 @@ struct FFmpegVideoCoder : public IPCMFrameProcessingPolicy {
std::string codec;
uint32_t bitrate;
bool PAL;
bool cut;
};

#endif // FFMPEGVIDEOCODER_H
23 changes: 0 additions & 23 deletions src/frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,5 @@ Frame::~Frame() {}

IFrame::PixelContainer Frame::render(uint8_t grayLevel,
uint8_t white_lvl) const {

/*
const auto pixel_heigth = SYNC_LINE_2 + 1 + width() + 1 + WHITE_WIDTH + 1;
std::vector<uint8_t> res(pixel_heigth * heigth());
myTwoDimArray<uint8_t> dest(res.data(), pixel_heigth, heigth());
myTwoDimArray<uint8_t> src((void *)m_pixels.data(),
static_cast<int32_t>(width()),
static_cast<int32_t>(heigth()));
for (auto l = 0; l < heigth(); ++l) {
auto line = dest.getLine(l);
line[SYNC_LINE_1] = grayLevel;
line[SYNC_LINE_2] = grayLevel;
std::memcpy(&line[5], src.getLine(l), heigth());
std::memset(&line[WHITE_LINE], white_lvl, WHITE_WIDTH);
}
*/

return m_pixels;
}
128 changes: 128 additions & 0 deletions src/frameextender.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include <cassert>
#include <cstring>

#include "MyTwoDimArray.h"

#include "frame.h"

#include "frameextender.h"

static const std::pair<int32_t, int32_t> &getExtends(bool isPal) {
// extemd frame up and down
static const std::pair<int32_t, int32_t> expends[]{
{18, 15}, // NTSC
{14, 21}, // PAL
};

return expends[isPal];
}

/*
auto container = frame->render();
auto src_accessor = container.getAccessor();
IFrame::PixelContainer ppFrame{width, heigth};
auto dest_accessor = ppFrame.getAccessor();
auto expend = getExtends(PAL);
int32_t first_src_line = std::max(crop_up - expend.first, 0);
uint32_t last_src_line = width;
uint32_t dest_line = std::max(expend.first - crop_up, 0);
auto line = first_src_line;
for (; line < 200; ++line, ++dest_line) {
auto _dest = dest_accessor.getLine(dest_line);
auto _src = src_accessor.getLine(line);
auto _w = frame->width();
std::memcpy(_dest, _src, _w);
}
*/

struct FrameProxy : public IFrame {
FrameProxy(std::unique_ptr<IFrame> &src_frame, int32_t src_heigth,
int32_t crop_up, int32_t crop_down, uint8_t factor)
: IFrame(src_frame->width() * factor, src_heigth - crop_up - crop_down),
src_frame{src_frame}, crop_up{crop_up}, crop_down{crop_down},
factor{factor} {}

PixelContainer render(uint8_t grayLevel = default_gray_lvl,
uint8_t white_lvl = default_white_lvl) const override {
auto src_pixels = src_frame->render(grayLevel, white_lvl);

auto wide_frame =
std::make_unique<Frame>(src_pixels.width() * factor, heigth());

auto src_accessor = src_pixels.getAccessor();
myTwoDimArray<uint8_t> dest_accessor{
wide_frame->data_pixels(), static_cast<int32_t>(wide_frame->width()),
static_cast<int32_t>(wide_frame->heigth())};

auto dest_line = 0;
auto src_line = 0;
auto lines_to_copy = src_pixels.heigth();

if (crop_up < 0) {
// extend black lines on top count crop_up
dest_line = -crop_up;
} else {
src_line = crop_up;
lines_to_copy -= crop_up;
}

if (crop_down > 0) {
lines_to_copy -= crop_down;
}

if (lines_to_copy > 0) {
for (auto l = 0; l < lines_to_copy; ++l, ++src_line, ++dest_line) {
auto src = src_accessor.getLine(src_line);
auto dst = dest_accessor.getLine(dest_line);
for (auto src_pixel_n = 0; src_pixel_n < src_accessor.getwidth();
++src_pixel_n) {
std::memset(dst, *src, factor);
dst += factor;
++src;
}
}
}

return wide_frame->render(grayLevel, white_lvl);
}

private:
std::unique_ptr<IFrame> &src_frame;
int32_t crop_up, crop_down;
uint8_t factor;
};

FrameExtender::FrameExtender(bool PAL, int32_t cut_top, int32_t cut_bot,
uint8_t factor)
: cut_top{cut_top}, cut_bot{cut_bot}, factor{factor},
src_heigth{}, PAL{PAL} {
assert(factor > 0);
}

void FrameExtender::Init(size_t width, size_t heigth) {
auto &extends = getExtends(PAL);

src_heigth = heigth;

auto result_heigth =
heigth + extends.first + extends.second - cut_top - cut_bot;

consumer->Init(width * factor, result_heigth);
}

void FrameExtender::operator()(std::unique_ptr<IFrame> &frame) {
auto &extends = getExtends(PAL);

int32_t crop_up = cut_top - extends.first;
int32_t crop_down = cut_bot - extends.second;

std::unique_ptr<IFrame> proxy{
new FrameProxy(frame, src_heigth, crop_up, crop_down, factor)};
(*consumer)(proxy);
}

void FrameExtender::finish() { consumer->finish(); }
11 changes: 9 additions & 2 deletions src/pixeldublicator.h → src/frameextender.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

#include "ipcmframeprocessingpolicy.h"

struct PixelDublicator : public IPCMFrameProcessingPolicy {
PixelDublicator(uint8_t factor = 1);
struct FrameExtender : public IPCMFrameProcessingPolicy {
FrameExtender(bool PAL = true, int32_t cut_top = 0, int32_t cut_bot = 0,
uint8_t factor = 1);

void Init(size_t width, size_t heigth) override;
void operator()(std::unique_ptr<IFrame> &frame) override;
Expand All @@ -17,7 +18,13 @@ struct PixelDublicator : public IPCMFrameProcessingPolicy {
private:
std::unique_ptr<IPCMFrameProcessingPolicy> consumer;

int32_t cut_top, cut_bot;

int32_t src_heigth;

uint8_t factor;

bool PAL;
};

#endif // PIXELDUBLICATOR_H
20 changes: 9 additions & 11 deletions src/iframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,20 @@ struct IFrame {
static constexpr uint8_t default_white_lvl = 255;

struct PixelContainer {
PixelContainer(size_t width, size_t heigth)
PixelContainer(int32_t width, int32_t heigth)
: pixels(width * heigth), m_width{width}, m_heigth{heigth} {}

myTwoDimArray<uint8_t> getAccessor() {
return myTwoDimArray<uint8_t>{pixels.data(),
static_cast<int32_t>(m_width),
static_cast<int32_t>(m_heigth)};
return myTwoDimArray<uint8_t>{pixels.data(), m_width, m_heigth};
}

size_t width() const { return m_width; }
size_t heigth() const { return m_heigth; }
int32_t width() const { return m_width; }
int32_t heigth() const { return m_heigth; }

std::vector<uint8_t> pixels;

private:
size_t m_width, m_heigth;
int32_t m_width, m_heigth;
};

enum {
Expand All @@ -38,19 +36,19 @@ struct IFrame {
WHITE_WIDTH = 4
};

IFrame(size_t width, size_t heigth) : m_width{width}, m_heigth{heigth} {}
IFrame(int32_t width, int32_t heigth) : m_width{width}, m_heigth{heigth} {}

virtual ~IFrame() {}

virtual PixelContainer
render(uint8_t grayLevel = default_gray_lvl,
uint8_t white_lvl = default_white_lvl) const = 0;

virtual size_t width() const { return m_width; }
virtual size_t heigth() const { return m_heigth; }
virtual int32_t width() const { return m_width; }
virtual int32_t heigth() const { return m_heigth; }

protected:
size_t m_width, m_heigth;
int32_t m_width, m_heigth;
};

#endif // IFRAME_H
Loading

0 comments on commit 03f90ac

Please sign in to comment.