in caffe2_customized_ops/video/customized_video_io.cc [240:332]
bool ReadClipFromVideoSequential(
std::string filename,
const int start_frm,
const int length,
const int height,
const int width,
const int sampling_rate,
float*& buffer) {
cv::VideoCapture cap;
cv::Mat img, img_origin;
buffer = nullptr;
int offset = 0;
int channel_size = 0;
int image_size = 0;
int data_size = 0;
cap.open(filename);
if (!cap.isOpened()) {
LOG(ERROR) << "Cannot open " << filename;
return false;
}
int num_of_frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
if (num_of_frames < length * sampling_rate) {
LOG(INFO) << filename << " does not have enough frames; having "
<< num_of_frames;
return false;
}
CAFFE_ENFORCE_GE(start_frm, 0, "start frame must be greater or equal to 0");
// Instead of random access, do sequentically access (avoid key-frame issue)
// This will keep start_frm frames
int sequential_counter = 0;
while (sequential_counter < start_frm) {
cap.read(img_origin);
sequential_counter++;
}
int end_frm = start_frm + length * sampling_rate;
CAFFE_ENFORCE_LE(
end_frm,
num_of_frames,
"end frame must be less or equal to num of frames");
for (int i = start_frm; i < end_frm; i++) {
if (sampling_rate > 1) {
// If sampling_rate > 1, purposely keep some frames
if ((i - start_frm) % sampling_rate != 0) {
cap.read(img_origin);
continue;
}
}
if (height > 0 && width > 0) {
cap.read(img_origin);
if (!img_origin.data) {
LOG(INFO) << filename << " has no data at frame " << i;
if (buffer != nullptr) {
delete[] buffer;
}
return false;
}
cv::resize(img_origin, img, cv::Size(width, height));
} else {
cap.read(img);
if (!img.data) {
LOG(ERROR) << "Could not open or find file " << filename;
if (buffer != nullptr) {
delete[] buffer;
}
return false;
}
}
// If this is the first frame, then we allocate memory for the buffer
if (i == start_frm) {
image_size = img.rows * img.cols;
channel_size = image_size * length;
data_size = channel_size * 3;
buffer = new float[data_size];
}
for (int c = 0; c < 3; c++) {
ImageChannelToBuffer(&img, buffer + c * channel_size + offset, c);
}
offset += image_size;
}
CAFFE_ENFORCE(offset == channel_size, "wrong offset size");
cap.release();
return true;
}