media/libvpx/vp9/decoder/vp9_onyxd_if.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     3  *
     4  *  Use of this source code is governed by a BSD-style license
     5  *  that can be found in the LICENSE file in the root of the source
     6  *  tree. An additional intellectual property rights grant can be found
     7  *  in the file PATENTS.  All contributing project authors may
     8  *  be found in the AUTHORS file in the root of the source tree.
     9  */
    11 #include <assert.h>
    12 #include <limits.h>
    13 #include <stdio.h>
    15 #include "vp9/common/vp9_onyxc_int.h"
    16 #if CONFIG_VP9_POSTPROC
    17 #include "vp9/common/vp9_postproc.h"
    18 #endif
    19 #include "vp9/decoder/vp9_onyxd.h"
    20 #include "vp9/decoder/vp9_onyxd_int.h"
    21 #include "vpx_mem/vpx_mem.h"
    22 #include "vp9/common/vp9_alloccommon.h"
    23 #include "vp9/common/vp9_loopfilter.h"
    24 #include "vp9/common/vp9_quant_common.h"
    25 #include "vpx_scale/vpx_scale.h"
    26 #include "vp9/common/vp9_systemdependent.h"
    27 #include "vpx_ports/vpx_timer.h"
    28 #include "vp9/decoder/vp9_decodframe.h"
    29 #include "vp9/decoder/vp9_detokenize.h"
    30 #include "./vpx_scale_rtcd.h"
    32 #define WRITE_RECON_BUFFER 0
    33 #if WRITE_RECON_BUFFER == 1
    34 static void recon_write_yuv_frame(const char *name,
    35                                   const YV12_BUFFER_CONFIG *s,
    36                                   int w, int _h) {
    37   FILE *yuv_file = fopen(name, "ab");
    38   const uint8_t *src = s->y_buffer;
    39   int h = _h;
    41   do {
    42     fwrite(src, w, 1,  yuv_file);
    43     src += s->y_stride;
    44   } while (--h);
    46   src = s->u_buffer;
    47   h = (_h + 1) >> 1;
    48   w = (w + 1) >> 1;
    50   do {
    51     fwrite(src, w, 1,  yuv_file);
    52     src += s->uv_stride;
    53   } while (--h);
    55   src = s->v_buffer;
    56   h = (_h + 1) >> 1;
    58   do {
    59     fwrite(src, w, 1, yuv_file);
    60     src += s->uv_stride;
    61   } while (--h);
    63   fclose(yuv_file);
    64 }
    65 #endif
    66 #if WRITE_RECON_BUFFER == 2
    67 void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
    68   // write the frame
    69   FILE *yframe;
    70   int i;
    71   char filename[255];
    73   snprintf(filename, sizeof(filename)-1, "dx\\y%04d.raw", this_frame);
    74   yframe = fopen(filename, "wb");
    76   for (i = 0; i < frame->y_height; i++)
    77     fwrite(frame->y_buffer + i * frame->y_stride,
    78            frame->y_width, 1, yframe);
    80   fclose(yframe);
    81   snprintf(filename, sizeof(filename)-1, "dx\\u%04d.raw", this_frame);
    82   yframe = fopen(filename, "wb");
    84   for (i = 0; i < frame->uv_height; i++)
    85     fwrite(frame->u_buffer + i * frame->uv_stride,
    86            frame->uv_width, 1, yframe);
    88   fclose(yframe);
    89   snprintf(filename, sizeof(filename)-1, "dx\\v%04d.raw", this_frame);
    90   yframe = fopen(filename, "wb");
    92   for (i = 0; i < frame->uv_height; i++)
    93     fwrite(frame->v_buffer + i * frame->uv_stride,
    94            frame->uv_width, 1, yframe);
    96   fclose(yframe);
    97 }
    98 #endif
   100 void vp9_initialize_dec() {
   101   static int init_done = 0;
   103   if (!init_done) {
   104     vp9_initialize_common();
   105     vp9_init_quant_tables();
   106     init_done = 1;
   107   }
   108 }
   110 static void init_macroblockd(VP9D_COMP *const pbi) {
   111   MACROBLOCKD *xd = &pbi->mb;
   112   struct macroblockd_plane *const pd = xd->plane;
   113   int i;
   115   for (i = 0; i < MAX_MB_PLANE; ++i) {
   116     pd[i].qcoeff  = pbi->qcoeff[i];
   117     pd[i].dqcoeff = pbi->dqcoeff[i];
   118     pd[i].eobs    = pbi->eobs[i];
   119   }
   120 }
   122 VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) {
   123   VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP));
   124   VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
   126   if (!cm)
   127     return NULL;
   129   vp9_zero(*pbi);
   131   if (setjmp(cm->error.jmp)) {
   132     cm->error.setjmp = 0;
   133     vp9_remove_decompressor(pbi);
   134     return NULL;
   135   }
   137   cm->error.setjmp = 1;
   138   vp9_initialize_dec();
   140   vp9_create_common(cm);
   142   pbi->oxcf = *oxcf;
   143   pbi->ready_for_new_data = 1;
   144   cm->current_video_frame = 0;
   146   // vp9_init_dequantizer() is first called here. Add check in
   147   // frame_init_dequantizer() to avoid unnecessary calling of
   148   // vp9_init_dequantizer() for every frame.
   149   vp9_init_dequantizer(cm);
   151   vp9_loop_filter_init(cm);
   153   cm->error.setjmp = 0;
   154   pbi->decoded_key_frame = 0;
   156   init_macroblockd(pbi);
   158   vp9_worker_init(&pbi->lf_worker);
   160   return pbi;
   161 }
   163 void vp9_remove_decompressor(VP9D_PTR ptr) {
   164   int i;
   165   VP9D_COMP *const pbi = (VP9D_COMP *)ptr;
   167   if (!pbi)
   168     return;
   170   vp9_remove_common(&pbi->common);
   171   vp9_worker_end(&pbi->lf_worker);
   172   vpx_free(pbi->lf_worker.data1);
   173   for (i = 0; i < pbi->num_tile_workers; ++i) {
   174     VP9Worker *const worker = &pbi->tile_workers[i];
   175     vp9_worker_end(worker);
   176     vpx_free(worker->data1);
   177     vpx_free(worker->data2);
   178   }
   179   vpx_free(pbi->tile_workers);
   180   vpx_free(pbi->mi_streams);
   181   vpx_free(pbi->above_context[0]);
   182   vpx_free(pbi->above_seg_context);
   183   vpx_free(pbi);
   184 }
   186 static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
   187     return a->y_height == b->y_height && a->y_width == b->y_width &&
   188            a->uv_height == b->uv_height && a->uv_width == b->uv_width;
   189 }
   191 vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr,
   192                                        VP9_REFFRAME ref_frame_flag,
   193                                        YV12_BUFFER_CONFIG *sd) {
   194   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   195   VP9_COMMON *cm = &pbi->common;
   197   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
   198    * encoder is using the frame buffers for. This is just a stub to keep the
   199    * vpxenc --test-decode functionality working, and will be replaced in a
   200    * later commit that adds VP9-specific controls for this functionality.
   201    */
   202   if (ref_frame_flag == VP9_LAST_FLAG) {
   203     YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]];
   204     if (!equal_dimensions(cfg, sd))
   205       vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
   206                          "Incorrect buffer dimensions");
   207     else
   208       vp8_yv12_copy_frame(cfg, sd);
   209   } else {
   210     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
   211                        "Invalid reference frame");
   212   }
   214   return cm->error.error_code;
   215 }
   218 vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
   219                                       YV12_BUFFER_CONFIG *sd) {
   220   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   221   VP9_COMMON *cm = &pbi->common;
   222   int *ref_fb_ptr = NULL;
   224   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
   225    * encoder is using the frame buffers for. This is just a stub to keep the
   226    * vpxenc --test-decode functionality working, and will be replaced in a
   227    * later commit that adds VP9-specific controls for this functionality.
   228    */
   229   if (ref_frame_flag == VP9_LAST_FLAG) {
   230     ref_fb_ptr = &pbi->common.active_ref_idx[0];
   231   } else if (ref_frame_flag == VP9_GOLD_FLAG) {
   232     ref_fb_ptr = &pbi->common.active_ref_idx[1];
   233   } else if (ref_frame_flag == VP9_ALT_FLAG) {
   234     ref_fb_ptr = &pbi->common.active_ref_idx[2];
   235   } else {
   236     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
   237                        "Invalid reference frame");
   238     return pbi->common.error.error_code;
   239   }
   241   if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
   242     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
   243                        "Incorrect buffer dimensions");
   244   } else {
   245     // Find an empty frame buffer.
   246     const int free_fb = get_free_fb(cm);
   247     // Decrease fb_idx_ref_cnt since it will be increased again in
   248     // ref_cnt_fb() below.
   249     cm->fb_idx_ref_cnt[free_fb]--;
   251     // Manage the reference counters and copy image.
   252     ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
   253     vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
   254   }
   256   return pbi->common.error.error_code;
   257 }
   260 int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) {
   261   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   262   VP9_COMMON *cm = &pbi->common;
   264   if (index < 0 || index >= NUM_REF_FRAMES)
   265     return -1;
   267   *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
   268   return 0;
   269 }
   271 /* If any buffer updating is signaled it should be done here. */
   272 static void swap_frame_buffers(VP9D_COMP *pbi) {
   273   int ref_index = 0, mask;
   274   VP9_COMMON *const cm = &pbi->common;
   276   for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
   277     if (mask & 1)
   278       ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index],
   279                  cm->new_fb_idx);
   280     ++ref_index;
   281   }
   283   cm->frame_to_show = get_frame_new_buffer(cm);
   284   cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   286   // Invalidate these references until the next frame starts.
   287   for (ref_index = 0; ref_index < 3; ref_index++)
   288     cm->active_ref_idx[ref_index] = INT_MAX;
   289 }
   291 int vp9_receive_compressed_data(VP9D_PTR ptr,
   292                                 size_t size, const uint8_t **psource,
   293                                 int64_t time_stamp) {
   294   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   295   VP9_COMMON *cm = &pbi->common;
   296   const uint8_t *source = *psource;
   297   int retcode = 0;
   299   /*if(pbi->ready_for_new_data == 0)
   300       return -1;*/
   302   if (ptr == 0)
   303     return -1;
   305   cm->error.error_code = VPX_CODEC_OK;
   307   pbi->source = source;
   308   pbi->source_sz = size;
   310   if (pbi->source_sz == 0) {
   311     /* This is used to signal that we are missing frames.
   312      * We do not know if the missing frame(s) was supposed to update
   313      * any of the reference buffers, but we act conservative and
   314      * mark only the last buffer as corrupted.
   315      *
   316      * TODO(jkoleszar): Error concealment is undefined and non-normative
   317      * at this point, but if it becomes so, [0] may not always be the correct
   318      * thing to do here.
   319      */
   320     if (cm->active_ref_idx[0] != INT_MAX)
   321       get_frame_ref_buffer(cm, 0)->corrupted = 1;
   322   }
   324   cm->new_fb_idx = get_free_fb(cm);
   326   if (setjmp(cm->error.jmp)) {
   327     cm->error.setjmp = 0;
   329     /* We do not know if the missing frame(s) was supposed to update
   330      * any of the reference buffers, but we act conservative and
   331      * mark only the last buffer as corrupted.
   332      *
   333      * TODO(jkoleszar): Error concealment is undefined and non-normative
   334      * at this point, but if it becomes so, [0] may not always be the correct
   335      * thing to do here.
   336      */
   337     if (cm->active_ref_idx[0] != INT_MAX)
   338       get_frame_ref_buffer(cm, 0)->corrupted = 1;
   340     if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
   341       cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   343     return -1;
   344   }
   346   cm->error.setjmp = 1;
   348   retcode = vp9_decode_frame(pbi, psource);
   350   if (retcode < 0) {
   351     cm->error.error_code = VPX_CODEC_ERROR;
   352     cm->error.setjmp = 0;
   353     if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
   354       cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   355     return retcode;
   356   }
   358   swap_frame_buffers(pbi);
   360 #if WRITE_RECON_BUFFER == 2
   361   if (cm->show_frame)
   362     write_dx_frame_to_file(cm->frame_to_show,
   363                            cm->current_video_frame);
   364   else
   365     write_dx_frame_to_file(cm->frame_to_show,
   366                            cm->current_video_frame + 1000);
   367 #endif
   369   if (!pbi->do_loopfilter_inline) {
   370     vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0);
   371   }
   373 #if WRITE_RECON_BUFFER == 2
   374   if (cm->show_frame)
   375     write_dx_frame_to_file(cm->frame_to_show,
   376                            cm->current_video_frame + 2000);
   377   else
   378     write_dx_frame_to_file(cm->frame_to_show,
   379                            cm->current_video_frame + 3000);
   380 #endif
   382   vp9_extend_frame_inner_borders(cm->frame_to_show,
   383                                  cm->subsampling_x,
   384                                  cm->subsampling_y);
   386 #if WRITE_RECON_BUFFER == 1
   387   if (cm->show_frame)
   388     recon_write_yuv_frame("recon.yuv", cm->frame_to_show,
   389                           cm->width, cm->height);
   390 #endif
   392   vp9_clear_system_state();
   394   cm->last_show_frame = cm->show_frame;
   395   if (cm->show_frame) {
   396     // current mip will be the prev_mip for the next frame
   397     MODE_INFO *temp = cm->prev_mip;
   398     MODE_INFO **temp2 = cm->prev_mi_grid_base;
   399     cm->prev_mip = cm->mip;
   400     cm->mip = temp;
   401     cm->prev_mi_grid_base = cm->mi_grid_base;
   402     cm->mi_grid_base = temp2;
   404     // update the upper left visible macroblock ptrs
   405     cm->mi = cm->mip + cm->mode_info_stride + 1;
   406     cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
   407     cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
   408     cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
   410     pbi->mb.mi_8x8 = cm->mi_grid_visible;
   411     pbi->mb.mi_8x8[0] = cm->mi;
   413     cm->current_video_frame++;
   414   }
   416   pbi->ready_for_new_data = 0;
   417   pbi->last_time_stamp = time_stamp;
   418   pbi->source_sz = 0;
   420   cm->error.setjmp = 0;
   421   return retcode;
   422 }
   424 int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd,
   425                       int64_t *time_stamp, int64_t *time_end_stamp,
   426                       vp9_ppflags_t *flags) {
   427   int ret = -1;
   428   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   430   if (pbi->ready_for_new_data == 1)
   431     return ret;
   433   /* ie no raw frame to show!!! */
   434   if (pbi->common.show_frame == 0)
   435     return ret;
   437   pbi->ready_for_new_data = 1;
   438   *time_stamp = pbi->last_time_stamp;
   439   *time_end_stamp = 0;
   441 #if CONFIG_VP9_POSTPROC
   442   ret = vp9_post_proc_frame(&pbi->common, sd, flags);
   443 #else
   445   if (pbi->common.frame_to_show) {
   446     *sd = *pbi->common.frame_to_show;
   447     sd->y_width = pbi->common.width;
   448     sd->y_height = pbi->common.height;
   449     sd->uv_width = sd->y_width >> pbi->common.subsampling_x;
   450     sd->uv_height = sd->y_height >> pbi->common.subsampling_y;
   452     ret = 0;
   453   } else {
   454     ret = -1;
   455   }
   457 #endif /*!CONFIG_POSTPROC*/
   458   vp9_clear_system_state();
   459   return ret;
   460 }

mercurial