Skip to content

Commit

Permalink
Let SimpleEncode be able to output bitstream
Browse files Browse the repository at this point in the history
Add outfile_path to SimpleEncode() with default value NULL.
The encoder will only output bitstream when outfile_path is set.

Change-Id: Ic68e5358ea454358c510bb0ae214f4201cb3db39
  • Loading branch information
angiebird committed Feb 6, 2020
1 parent 8a5cb08 commit 2c46556
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 23 deletions.
30 changes: 19 additions & 11 deletions ivfenc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,35 @@
#include "vpx/vpx_encoder.h"
#include "vpx_ports/mem_ops.h"

void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
unsigned int fourcc, int frame_cnt) {
void ivf_write_file_header_with_video_info(FILE *outfile, unsigned int fourcc,
int frame_cnt, int frame_width,
int frame_height,
vpx_rational_t timebase) {
char header[32];

header[0] = 'D';
header[1] = 'K';
header[2] = 'I';
header[3] = 'F';
mem_put_le16(header + 4, 0); // version
mem_put_le16(header + 6, 32); // header size
mem_put_le32(header + 8, fourcc); // fourcc
mem_put_le16(header + 12, cfg->g_w); // width
mem_put_le16(header + 14, cfg->g_h); // height
mem_put_le32(header + 16, cfg->g_timebase.den); // rate
mem_put_le32(header + 20, cfg->g_timebase.num); // scale
mem_put_le32(header + 24, frame_cnt); // length
mem_put_le32(header + 28, 0); // unused
mem_put_le16(header + 4, 0); // version
mem_put_le16(header + 6, 32); // header size
mem_put_le32(header + 8, fourcc); // fourcc
mem_put_le16(header + 12, frame_width); // width
mem_put_le16(header + 14, frame_height); // height
mem_put_le32(header + 16, timebase.den); // rate
mem_put_le32(header + 20, timebase.num); // scale
mem_put_le32(header + 24, frame_cnt); // length
mem_put_le32(header + 28, 0); // unused

fwrite(header, 1, 32, outfile);
}

void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
unsigned int fourcc, int frame_cnt) {
ivf_write_file_header_with_video_info(outfile, fourcc, frame_cnt, cfg->g_w,
cfg->g_h, cfg->g_timebase);
}

void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
char header[12];

Expand Down
7 changes: 7 additions & 0 deletions ivfenc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@

#include "./tools_common.h"

#include "vpx/vpx_encoder.h"

struct vpx_codec_enc_cfg;
struct vpx_codec_cx_pkt;

#ifdef __cplusplus
extern "C" {
#endif

void ivf_write_file_header_with_video_info(FILE *outfile, unsigned int fourcc,
int frame_cnt, int frame_width,
int frame_height,
vpx_rational_t timebase);

void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
uint32_t fourcc, int frame_cnt);

Expand Down
51 changes: 41 additions & 10 deletions vp9/simple_encode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <memory>
#include <vector>
#include "./ivfenc.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_enums.h"
#include "vp9/common/vp9_onyxc_int.h"
Expand Down Expand Up @@ -122,6 +123,13 @@ static INLINE vpx_rational_t make_vpx_rational(int num, int den) {
return v;
}

static INLINE vpx_rational_t inverse_vpx_rational(vpx_rational_t v) {
vpx_rational_t inverse_v;
inverse_v.num = v.den;
inverse_v.den = v.num;
return inverse_v;
}

static INLINE FrameType
get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) {
// TODO(angiebird): Figure out if we need frame type other than key frame,
Expand Down Expand Up @@ -517,7 +525,7 @@ static void UpdateGroupOfPicture(const VP9_COMP *cpi,
SimpleEncode::SimpleEncode(int frame_width, int frame_height,
int frame_rate_num, int frame_rate_den,
int target_bitrate, int num_frames,
const char *infile_path) {
const char *infile_path, const char *outfile_path) {
impl_ptr_ = std::unique_ptr<EncodeImpl>(new EncodeImpl());
frame_width_ = frame_width;
frame_height_ = frame_height;
Expand All @@ -526,7 +534,12 @@ SimpleEncode::SimpleEncode(int frame_width, int frame_height,
target_bitrate_ = target_bitrate;
num_frames_ = num_frames;
// TODO(angirbid): Should we keep a file pointer here or keep the file_path?
file_ = fopen(infile_path, "r");
in_file_ = fopen(infile_path, "r");
if (outfile_path != NULL) {
out_file_ = fopen(outfile_path, "w");
} else {
out_file_ = NULL;
}
impl_ptr_->cpi = NULL;
impl_ptr_->img_fmt = VPX_IMG_FMT_I420;
}
Expand All @@ -546,11 +559,11 @@ void SimpleEncode::ComputeFirstPassStats() {
#endif
vpx_image_t img;
vpx_img_alloc(&img, impl_ptr_->img_fmt, frame_width_, frame_height_, 1);
rewind(file_);
rewind(in_file_);
impl_ptr_->first_pass_stats.clear();
for (i = 0; i < num_frames_; ++i) {
assert(!vp9_lookahead_full(lookahead));
if (img_read(&img, file_)) {
if (img_read(&img, in_file_)) {
int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
int64_t ts_start =
timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx);
Expand Down Expand Up @@ -581,7 +594,7 @@ void SimpleEncode::ComputeFirstPassStats() {
// TODO(angiebird): Store the total_stats apart form first_pass_stats
impl_ptr_->first_pass_stats.push_back(vp9_get_total_stats(&cpi->twopass));
free_encoder(cpi);
rewind(file_);
rewind(in_file_);
vpx_img_free(&img);
}

Expand Down Expand Up @@ -625,14 +638,22 @@ void SimpleEncode::StartEncode() {
vpx_img_alloc(&impl_ptr_->tmp_img, impl_ptr_->img_fmt, frame_width_,
frame_height_, 1);
UpdateGroupOfPicture(impl_ptr_->cpi, &group_of_picture_);
rewind(file_);
rewind(in_file_);

if (out_file_ != NULL) {
const char *fourcc = "VP90";
vpx_rational_t time_base = inverse_vpx_rational(frame_rate);
ivf_write_file_header_with_video_info(out_file_, *(const uint32_t *)fourcc,
num_frames_, frame_width_,
frame_height_, time_base);
}
}

void SimpleEncode::EndEncode() {
free_encoder(impl_ptr_->cpi);
impl_ptr_->cpi = nullptr;
vpx_img_free(&impl_ptr_->tmp_img);
rewind(file_);
rewind(in_file_);
}

int SimpleEncode::GetKeyFrameGroupSize(int key_frame_index) const {
Expand Down Expand Up @@ -666,7 +687,7 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
while (!vp9_lookahead_full(lookahead)) {
// TODO(angiebird): Check whether we can move this file read logics to
// lookahead
if (img_read(&impl_ptr_->tmp_img, file_)) {
if (img_read(&impl_ptr_->tmp_img, in_file_)) {
int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
int64_t ts_start =
timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts, next_show_idx);
Expand Down Expand Up @@ -694,6 +715,13 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
&encode_frame_result->coding_data_byte_size,
encode_frame_result->coding_data.get(), &time_stamp,
&time_end, flush, &encode_frame_info);
if (out_file_ != NULL) {
ivf_write_frame_header(out_file_, time_stamp,
encode_frame_result->coding_data_byte_size);
fwrite(encode_frame_result->coding_data.get(), 1,
encode_frame_result->coding_data_byte_size, out_file_);
}

// vp9_get_compressed_data is expected to encode a frame every time, so the
// data size should be greater than zero.
if (encode_frame_result->coding_data_byte_size <= 0) {
Expand Down Expand Up @@ -763,8 +791,11 @@ uint64_t SimpleEncode::GetFramePixelCount() const {
}

SimpleEncode::~SimpleEncode() {
if (this->file_ != NULL) {
fclose(this->file_);
if (in_file_ != NULL) {
fclose(in_file_);
}
if (out_file_ != NULL) {
fclose(out_file_);
}
}

Expand Down
7 changes: 5 additions & 2 deletions vp9/simple_encode.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,11 @@ struct GroupOfPicture {

class SimpleEncode {
public:
// When outfile_path is set, the encoder will output the bitstream in ivf
// format.
SimpleEncode(int frame_width, int frame_height, int frame_rate_num,
int frame_rate_den, int target_bitrate, int num_frames,
const char *infile_path);
const char *infile_path, const char *outfile_path = NULL);
~SimpleEncode();
SimpleEncode(SimpleEncode &) = delete;
SimpleEncode &operator=(const SimpleEncode &) = delete;
Expand Down Expand Up @@ -268,7 +270,8 @@ class SimpleEncode {
int frame_rate_den_;
int target_bitrate_;
int num_frames_;
std::FILE *file_;
std::FILE *in_file_;
std::FILE *out_file_;
std::unique_ptr<EncodeImpl> impl_ptr_;

GroupOfPicture group_of_picture_;
Expand Down

0 comments on commit 2c46556

Please sign in to comment.