]> granicus.if.org Git - libvpx/commitdiff
vpxenc: generate multistream file
authorJohn Koleszar <jkoleszar@google.com>
Tue, 6 Mar 2012 01:18:07 +0000 (17:18 -0800)
committerJohn Koleszar <jkoleszar@google.com>
Thu, 8 Mar 2012 20:19:09 +0000 (12:19 -0800)
Add the ability to append mode/mv records onto the bitstream.

Change-Id: I83d3125ffe8e6c25dd9e2fa900c963f4f571e6f9

vp8/vp8_cx_iface.c
vpxenc.c

index 42da7be80599440b1061b1c9f0c429e2624e2d5e..31254d47b034e7be7acc9182da4044520930ed1b 100644 (file)
@@ -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,
index c237008ee9060333296c0dd921be52b64613a712..d5d366e47d3e20afd9e845a42f8118453fdd2697 100644 (file)
--- 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);
         }