From 0a50a29121cdeaa1e3bb45c0cc771a0f8fe29fee Mon Sep 17 00:00:00 2001 From: John Koleszar Date: Mon, 5 Mar 2012 17:18:07 -0800 Subject: [PATCH] vpxenc: generate multistream file Add the ability to append mode/mv records onto the bitstream. Change-Id: I83d3125ffe8e6c25dd9e2fa900c963f4f571e6f9 --- vp8/vp8_cx_iface.c | 52 ++++++++++++++++++- vpxenc.c | 123 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index 42da7be80..31254d47b 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -77,6 +77,18 @@ static const struct extraconfig_map extracfg_map[] = } }; + +struct cx_data_iter +{ + struct vpx_codec_cx_pkt pkt; + int frame_out; + int pkt_list_done; + vpx_codec_iter_t pkt_list_iter; + int mode_info_done; + int mode_info_row; +}; + + struct vpx_codec_alg_priv { vpx_codec_priv_t base; @@ -92,6 +104,7 @@ struct vpx_codec_alg_priv vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed int deprecated_mode; unsigned int fixed_kf_cntr; + struct cx_data_iter cx_data_iter; }; @@ -952,7 +965,44 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx, vpx_codec_iter_t *iter) { - return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter); + if(!*iter) + { + memset(&ctx->cx_data_iter, 0, sizeof(ctx->cx_data_iter)); + *iter = &ctx->cx_data_iter; + } + if(!ctx->cx_data_iter.pkt_list_done) + { + const vpx_codec_cx_pkt_t *pkt; + + pkt = vpx_codec_pkt_list_get(&ctx->pkt_list.head, + &ctx->cx_data_iter.pkt_list_iter); + if(pkt) + { + ctx->cx_data_iter.frame_out = 1; + return pkt; + } + ctx->cx_data_iter.pkt_list_done = 1; + } + if(!ctx->cx_data_iter.frame_out) + return NULL; + if(!ctx->cx_data_iter.mode_info_done) + { + vpx_codec_cx_pkt_t *pkt = &ctx->cx_data_iter.pkt; + + if(ctx->cx_data_iter.mode_info_row < ctx->cpi->common.mb_rows) + { + pkt->kind = VPX_CODEC_CUSTOM_PKT; + pkt->data.raw.buf = ctx->cpi->common.mi + + ctx->cpi->common.mode_info_stride + * ctx->cx_data_iter.mode_info_row; + pkt->data.raw.sz = sizeof(MODE_INFO) * ctx->cpi->common.mb_cols; + ctx->cx_data_iter.mode_info_row++; + return pkt; + } + else + ctx->cx_data_iter.mode_info_done = 1; + } + return NULL; } static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx, diff --git a/vpxenc.c b/vpxenc.c index c237008ee..d5d366e47 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -2239,6 +2239,124 @@ static void get_cx_data(struct stream_state *stream, } +struct link_record +{ + uint32_t sz; + uint16_t w; + uint16_t h; +}; + +static void +write_multistream_file(struct stream_state *streams, + struct global_config *global, + int *got_data) +{ + const vpx_codec_cx_pkt_t *pkt; + vpx_codec_cx_pkt_t outpkt = {0}; + int newsz; + + FOREACH_STREAM({ + vpx_codec_iter_t iter = NULL; + const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg; + struct link_record link = {0}; + + while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) + { + *got_data = 1; + + switch (pkt->kind) + { + case VPX_CODEC_CX_FRAME_PKT: + stream->frames_out++; + fprintf(stderr, " %6luF", + (unsigned long)pkt->data.frame.sz); + + update_rate_histogram(&stream->rate_hist, cfg, pkt); + stream->nbytes += pkt->data.raw.sz; + + if(stream == streams) + { + outpkt = *pkt; + outpkt.data.raw.buf = malloc(outpkt.data.raw.sz); + memcpy(outpkt.data.raw.buf, pkt->data.raw.buf, pkt->data.raw.sz); + } + break; + case VPX_CODEC_STATS_PKT: + stream->frames_out++; + fprintf(stderr, " %6luS", + (unsigned long)pkt->data.twopass_stats.sz); + stats_write(&stream->stats, + pkt->data.twopass_stats.buf, + pkt->data.twopass_stats.sz); + stream->nbytes += pkt->data.raw.sz; + break; + case VPX_CODEC_PSNR_PKT: + + if (global->show_psnr) + { + int i; + + stream->psnr_sse_total += pkt->data.psnr.sse[0]; + stream->psnr_samples_total += pkt->data.psnr.samples[0]; + for (i = 0; i < 4; i++) + { + fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]); + stream->psnr_totals[i] += pkt->data.psnr.psnr[i]; + } + stream->psnr_count++; + } + + break; + default: + /* Append other data packets to outpkt */ + newsz = outpkt.data.raw.sz + pkt->data.raw.sz; + outpkt.data.raw.buf = realloc(outpkt.data.raw.buf, newsz); + memcpy((char*)outpkt.data.raw.buf + outpkt.data.raw.sz, + pkt->data.raw.buf, pkt->data.raw.sz); + outpkt.data.raw.sz = newsz; + link.sz += pkt->data.raw.sz; + break; + } + } + + if(link.sz) + { + link.w = cfg->g_w; + link.h = cfg->g_h; + link.sz |= (stream == streams)?0:(1<<31); + newsz = outpkt.data.raw.sz + sizeof(link); + outpkt.data.raw.buf = realloc(outpkt.data.raw.buf, newsz); + memcpy((char*)outpkt.data.raw.buf + outpkt.data.raw.sz, + &link, sizeof(link)); + outpkt.data.raw.sz = newsz; + } + + }); + if(outpkt.data.raw.sz) + { + const struct vpx_codec_enc_cfg *cfg = &streams->config.cfg; + struct stream_state *stream = streams; + const vpx_codec_cx_pkt_t *pkt = &outpkt; + + if(stream->config.write_webm) + { + /* Update the hash */ + if(!stream->ebml.debug) + stream->hash = murmur(pkt->data.frame.buf, + pkt->data.frame.sz, stream->hash); + + write_webm_block(&streams->ebml, cfg, pkt); + } + else + { + write_ivf_frame_header(stream->file, pkt); + if(fwrite(pkt->data.frame.buf, 1, + pkt->data.frame.sz, stream->file)); + } + free(outpkt.data.raw.buf); + } +} + static void show_psnr(struct stream_state *stream) { int i; @@ -2432,7 +2550,10 @@ int main(int argc, const char **argv_) FOREACH_STREAM(update_quantizer_histogram(stream)); got_data = 0; - FOREACH_STREAM(get_cx_data(stream, &global, &got_data)); + if(1) + write_multistream_file(streams, &global, &got_data); + else + FOREACH_STREAM(get_cx_data(stream, &global, &got_data)); fflush(stdout); } -- 2.40.0