implement encoding a part of the host video

This commit is contained in:
falsycat 2022-10-14 00:02:48 +09:00
parent 0fde521ffe
commit 8262bf29b2
2 changed files with 70 additions and 39 deletions

View File

@ -36,6 +36,15 @@ ValueFlag<int32_t> bh {
ValueFlag<int32_t> utime {
parser, "10", "duration of each feature (frame)", {"utime"}, 10,
};
ValueFlag<int32_t> dur {
parser, "0", "number of features to be extracted (ut)", {"dur"}, 0,
};
ValueFlag<int32_t> offset {
parser, "0", "number of offset frames to start extraction", {"offset"}, 0,
};
Flag only_body {
parser, "only-body", "cut off head and tail that no feature is embedded", {"only-body"},
};
Flag uvfix {
parser, "uvfix", "fix UV values in feature", {"uvfix"},
@ -91,9 +100,11 @@ static void Embed(int32_t t, Frame& dst, const Frame& base) {
}
static void Exec() {
const auto bw = args::get(param::bw);
const auto bh = args::get(param::bh);
const auto ut = args::get(param::utime);
const auto bw = args::get(param::bw);
const auto bh = args::get(param::bh);
const auto ut = args::get(param::utime);
const auto dur = args::get(param::dur);
const auto offset = args::get(param::offset);
Enforce(bw > 0 && bh > 0, "block size must be greater than 0");
Enforce(ut > 0, "utime must be greater than 0");
@ -151,10 +162,10 @@ static void Exec() {
// calc params
const auto tscale = tra.timescale;
const auto dur =
const auto dur_t =
(static_cast<uint64_t>(tra.duration_hi) << 32) |
static_cast<uint64_t>(tra.duration_lo);
const auto dursec = static_cast<float>(dur)/static_cast<float>(tscale);
const auto dursec = static_cast<float>(dur_t)/static_cast<float>(tscale);
const float fps = static_cast<float>(tra.sample_count)/dursec;
const auto fps9 = static_cast<int>(90000/fps);
@ -218,10 +229,10 @@ static void Exec() {
// decode frame
Frame bf = {};
int32_t t = 0;
int32_t fidx = 0;
for (size_t si = 0; si < tra.sample_count; ++si) {
unsigned fsz, time, dur;
const auto off = MP4D_frame_offset(&dem, ti, si, &fsz, &time, &dur);
unsigned fsz, ftime, fdur;
const auto off = MP4D_frame_offset(&dem, ti, si, &fsz, &ftime, &fdur);
srcst.seekg(off);
Enforce(!!srcst, "NAL seek failure");
@ -247,37 +258,48 @@ static void Exec() {
// handle decoded frame
if (frame.iBufferStatus) {
bool encode_frame = !param::only_body;
bool keep_frame = false;
// alter the frame if it's not the first
Frame cf = {yuv, frame};
if (t%ut > 0) {
Embed(t/ut, cf, bf);
if (offset <= fidx && (dur == 0 || fidx-offset < dur*ut)) {
const auto t = (fidx-offset)/ut;
const auto tf = (fidx-offset)%ut;
if (tf > 0) {
Embed(t, cf, bf);
}
encode_frame = true;
keep_frame = (tf == 0);
}
// encode
SFrameBSInfo info;
SSourcePicture pic = cf.GetSourcePic();
Enforce(cmResultSuccess == enc->EncodeFrame(&pic, &info),
"encode failure");
if (encode_frame) {
SFrameBSInfo info;
SSourcePicture pic = cf.GetSourcePic();
Enforce(cmResultSuccess == enc->EncodeFrame(&pic, &info),
"encode failure");
// write buffer
if (info.eFrameType != videoFrameTypeSkip) {
for (int li = 0; li < info.iLayerNum; ++li) {
const auto& l = info.sLayerInfo[li];
// write buffer
if (info.eFrameType != videoFrameTypeSkip) {
for (int li = 0; li < info.iLayerNum; ++li) {
const auto& l = info.sLayerInfo[li];
uint8_t* buf = l.pBsBuf;
for (int ni = 0; ni < l.iNalCount; ++ni) {
mp4_h26x_write_nal(
&writer, buf, l.pNalLengthInByte[ni], fps9);
buf += l.pNalLengthInByte[ni];
uint8_t* buf = l.pBsBuf;
for (int ni = 0; ni < l.iNalCount; ++ni) {
mp4_h26x_write_nal(
&writer, buf, l.pNalLengthInByte[ni], fps9);
buf += l.pNalLengthInByte[ni];
}
}
}
}
// save the frame if it's the first
if (t%ut == 0) {
if (keep_frame) {
bf = std::move(cf);
}
++t;
++fidx;
}
i += sz;
}

View File

@ -35,6 +35,12 @@ ValueFlag<int32_t> bh {
ValueFlag<int32_t> utime {
parser, "10", "duration of each feature (frame)", {"utime"}, 10,
};
ValueFlag<int32_t> dur {
parser, "0", "number of features to be extracted (ut)", {"dur"}, 0,
};
ValueFlag<int32_t> offset {
parser, "0", "number of offset frames to start extraction", {"offset"}, 0,
};
ValueFlag<int32_t> bmix {
parser, "8", "x interval of blockmatch (px)", {"bm-ix"}, 8,
@ -184,9 +190,11 @@ static void EachFrame(int32_t t, const Frame& cf, const Frame& pf) {
}
static void Exec() {
const auto bw = args::get(param::bw);
const auto bh = args::get(param::bh);
const auto ut = args::get(param::utime);
const auto bw = args::get(param::bw);
const auto bh = args::get(param::bh);
const auto ut = args::get(param::utime);
const auto dur = args::get(param::dur);
const auto offset = args::get(param::offset);
Enforce(bw > 0 && bh > 0, "block size must be greater than 0");
Enforce(ut > 0, "utime must be greater than 0");
@ -265,10 +273,10 @@ static void Exec() {
// decode frame
Frame pf = {};
size_t t = 0;
int32_t fidx = 0;
for (size_t si = 0; si < tra.sample_count; ++si) {
unsigned fsz, time, dur;
const auto off = MP4D_frame_offset(&dem, ti, si, &fsz, &time, &dur);
unsigned fsz, ftime, fdur;
const auto off = MP4D_frame_offset(&dem, ti, si, &fsz, &ftime, &fdur);
vst.seekg(off);
Enforce(!!vst, "NAL seek failure");
@ -291,16 +299,17 @@ static void Exec() {
Enforce(ret == 0, "frame decode failure");
i += sz;
Frame cf = {yuv, frame};
if (cf.w == 0 || cf.h == 0) continue;
if (offset <= fidx && (dur == 0 || fidx-offset < dur*ut)) {
Frame cf = {yuv, frame};
if (cf.w == 0 || cf.h == 0) continue;
const auto utf = t%ut;
if (utf > 0) {
EachFrame(utf, cf, pf);
const auto tf = (fidx-offset)%ut;
if (tf > 0) {
EachFrame(tf, cf, pf);
}
pf = std::move(cf);
}
pf = std::move(cf);
++t;
++fidx;
}
}
}