tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

yv12extend.c (17974B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include <assert.h>
     13 
     14 #include "config/aom_config.h"
     15 #include "config/aom_scale_rtcd.h"
     16 
     17 #include "aom/aom_integer.h"
     18 #include "aom_mem/aom_mem.h"
     19 #include "aom_ports/mem.h"
     20 #include "aom_scale/yv12config.h"
     21 
     22 static void extend_plane(uint8_t *const src, int src_stride, int width,
     23                         int height, int extend_top, int extend_left,
     24                         int extend_bottom, int extend_right, int v_start,
     25                         int v_end) {
     26  assert(src != NULL);
     27  int i;
     28  const int linesize = extend_left + extend_right + width;
     29  assert(linesize <= src_stride);
     30 
     31  /* copy the left and right most columns out */
     32  uint8_t *src_ptr1 = src + v_start * src_stride;
     33  uint8_t *src_ptr2 = src + v_start * src_stride + width - 1;
     34  uint8_t *dst_ptr1 = src + v_start * src_stride - extend_left;
     35  uint8_t *dst_ptr2 = src_ptr2 + 1;
     36 
     37  for (i = v_start; i < v_end; ++i) {
     38    memset(dst_ptr1, src_ptr1[0], extend_left);
     39    memset(dst_ptr2, src_ptr2[0], extend_right);
     40    src_ptr1 += src_stride;
     41    src_ptr2 += src_stride;
     42    dst_ptr1 += src_stride;
     43    dst_ptr2 += src_stride;
     44  }
     45 
     46  /* Now copy the top and bottom lines into each line of the respective
     47   * borders
     48   */
     49  src_ptr1 = src - extend_left;
     50  dst_ptr1 = src_ptr1 + src_stride * -extend_top;
     51 
     52  for (i = 0; i < extend_top; ++i) {
     53    memcpy(dst_ptr1, src_ptr1, linesize);
     54    dst_ptr1 += src_stride;
     55  }
     56 
     57  src_ptr2 = src_ptr1 + src_stride * (height - 1);
     58  dst_ptr2 = src_ptr2;
     59 
     60  for (i = 0; i < extend_bottom; ++i) {
     61    dst_ptr2 += src_stride;
     62    memcpy(dst_ptr2, src_ptr2, linesize);
     63  }
     64 }
     65 
     66 #if CONFIG_AV1_HIGHBITDEPTH
     67 static void extend_plane_high(uint8_t *const src8, int src_stride, int width,
     68                              int height, int extend_top, int extend_left,
     69                              int extend_bottom, int extend_right, int v_start,
     70                              int v_end) {
     71  int i;
     72  const int linesize = extend_left + extend_right + width;
     73  assert(linesize <= src_stride);
     74  uint16_t *src = CONVERT_TO_SHORTPTR(src8);
     75 
     76  /* copy the left and right most columns out */
     77  uint16_t *src_ptr1 = src + v_start * src_stride;
     78  uint16_t *src_ptr2 = src + v_start * src_stride + width - 1;
     79  uint16_t *dst_ptr1 = src + v_start * src_stride - extend_left;
     80  uint16_t *dst_ptr2 = src_ptr2 + 1;
     81 
     82  for (i = v_start; i < v_end; ++i) {
     83    aom_memset16(dst_ptr1, src_ptr1[0], extend_left);
     84    aom_memset16(dst_ptr2, src_ptr2[0], extend_right);
     85    src_ptr1 += src_stride;
     86    src_ptr2 += src_stride;
     87    dst_ptr1 += src_stride;
     88    dst_ptr2 += src_stride;
     89  }
     90 
     91  /* Now copy the top and bottom lines into each line of the respective
     92   * borders
     93   */
     94  src_ptr1 = src - extend_left;
     95  dst_ptr1 = src_ptr1 + src_stride * -extend_top;
     96 
     97  for (i = 0; i < extend_top; ++i) {
     98    memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
     99    dst_ptr1 += src_stride;
    100  }
    101 
    102  src_ptr2 = src_ptr1 + src_stride * (height - 1);
    103  dst_ptr2 = src_ptr2;
    104 
    105  for (i = 0; i < extend_bottom; ++i) {
    106    dst_ptr2 += src_stride;
    107    memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
    108  }
    109 }
    110 #endif  // CONFIG_AV1_HIGHBITDEPTH
    111 
    112 void aom_extend_frame_borders_plane_row_c(const YV12_BUFFER_CONFIG *ybf,
    113                                          int plane, int v_start, int v_end) {
    114  const int ext_size = ybf->border;
    115  const int ss_x = ybf->subsampling_x;
    116  const int ss_y = ybf->subsampling_y;
    117 
    118  assert(ybf->y_height - ybf->y_crop_height < 16);
    119  assert(ybf->y_width - ybf->y_crop_width < 16);
    120  assert(ybf->y_height - ybf->y_crop_height >= 0);
    121  assert(ybf->y_width - ybf->y_crop_width >= 0);
    122 
    123  const int is_uv = plane > 0;
    124  const int top = ext_size >> (is_uv ? ss_y : 0);
    125  const int left = ext_size >> (is_uv ? ss_x : 0);
    126  const int bottom = top + ybf->heights[is_uv] - ybf->crop_heights[is_uv];
    127  const int right = left + ybf->widths[is_uv] - ybf->crop_widths[is_uv];
    128  const int extend_top_border = (v_start == 0);
    129  const int extend_bottom_border = (v_end == ybf->crop_heights[is_uv]);
    130 
    131 #if CONFIG_AV1_HIGHBITDEPTH
    132  if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
    133    extend_plane_high(ybf->buffers[plane], ybf->strides[is_uv],
    134                      ybf->crop_widths[is_uv], ybf->crop_heights[is_uv],
    135                      extend_top_border ? top : 0, left,
    136                      extend_bottom_border ? bottom : 0, right, v_start, v_end);
    137    return;
    138  }
    139 #endif
    140 
    141  extend_plane(ybf->buffers[plane], ybf->strides[is_uv],
    142               ybf->crop_widths[is_uv], ybf->crop_heights[is_uv],
    143               extend_top_border ? top : 0, left,
    144               extend_bottom_border ? bottom : 0, right, v_start, v_end);
    145 }
    146 
    147 void aom_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf,
    148                                     const int num_planes) {
    149  assert(ybf->border % 2 == 0);
    150  assert(ybf->y_height - ybf->y_crop_height < 16);
    151  assert(ybf->y_width - ybf->y_crop_width < 16);
    152  assert(ybf->y_height - ybf->y_crop_height >= 0);
    153  assert(ybf->y_width - ybf->y_crop_width >= 0);
    154 
    155 #if CONFIG_AV1_HIGHBITDEPTH
    156  if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
    157    for (int plane = 0; plane < num_planes; ++plane) {
    158      const int is_uv = plane > 0;
    159      const int plane_border = ybf->border >> is_uv;
    160      extend_plane_high(
    161          ybf->buffers[plane], ybf->strides[is_uv], ybf->crop_widths[is_uv],
    162          ybf->crop_heights[is_uv], plane_border, plane_border,
    163          plane_border + ybf->heights[is_uv] - ybf->crop_heights[is_uv],
    164          plane_border + ybf->widths[is_uv] - ybf->crop_widths[is_uv], 0,
    165          ybf->crop_heights[is_uv]);
    166    }
    167    return;
    168  }
    169 #endif
    170 
    171  for (int plane = 0; plane < num_planes; ++plane) {
    172    const int is_uv = plane > 0;
    173    const int plane_border = ybf->border >> is_uv;
    174    extend_plane(ybf->buffers[plane], ybf->strides[is_uv],
    175                 ybf->crop_widths[is_uv], ybf->crop_heights[is_uv],
    176                 plane_border, plane_border,
    177                 plane_border + ybf->heights[is_uv] - ybf->crop_heights[is_uv],
    178                 plane_border + ybf->widths[is_uv] - ybf->crop_widths[is_uv], 0,
    179                 ybf->crop_heights[is_uv]);
    180  }
    181 }
    182 
    183 static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size,
    184                         const int num_planes) {
    185  const int ss_x = ybf->subsampling_x;
    186  const int ss_y = ybf->subsampling_y;
    187 
    188  assert(ybf->y_height - ybf->y_crop_height < 16);
    189  assert(ybf->y_width - ybf->y_crop_width < 16);
    190  assert(ybf->y_height - ybf->y_crop_height >= 0);
    191  assert(ybf->y_width - ybf->y_crop_width >= 0);
    192 
    193 #if CONFIG_AV1_HIGHBITDEPTH
    194  if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
    195    for (int plane = 0; plane < num_planes; ++plane) {
    196      const int is_uv = plane > 0;
    197      const int top = ext_size >> (is_uv ? ss_y : 0);
    198      const int left = ext_size >> (is_uv ? ss_x : 0);
    199      const int bottom = top + ybf->heights[is_uv] - ybf->crop_heights[is_uv];
    200      const int right = left + ybf->widths[is_uv] - ybf->crop_widths[is_uv];
    201      extend_plane_high(ybf->buffers[plane], ybf->strides[is_uv],
    202                        ybf->crop_widths[is_uv], ybf->crop_heights[is_uv], top,
    203                        left, bottom, right, 0, ybf->crop_heights[is_uv]);
    204    }
    205    return;
    206  }
    207 #endif
    208 
    209  for (int plane = 0; plane < num_planes; ++plane) {
    210    const int is_uv = plane > 0;
    211    const int top = ext_size >> (is_uv ? ss_y : 0);
    212    const int left = ext_size >> (is_uv ? ss_x : 0);
    213    const int bottom = top + ybf->heights[is_uv] - ybf->crop_heights[is_uv];
    214    const int right = left + ybf->widths[is_uv] - ybf->crop_widths[is_uv];
    215    extend_plane(ybf->buffers[plane], ybf->strides[is_uv],
    216                 ybf->crop_widths[is_uv], ybf->crop_heights[is_uv], top, left,
    217                 bottom, right, 0, ybf->crop_heights[is_uv]);
    218  }
    219 }
    220 
    221 void aom_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf, const int num_planes) {
    222  extend_frame(ybf, ybf->border, num_planes);
    223 }
    224 
    225 #if CONFIG_AV1_HIGHBITDEPTH
    226 static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
    227  uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
    228  uint16_t *src = CONVERT_TO_SHORTPTR(src8);
    229  memcpy(dst, src, num * sizeof(uint16_t));
    230 }
    231 #endif
    232 
    233 // Copies the source image into the destination image and updates the
    234 // destination's UMV borders.
    235 // Note: The frames are assumed to be identical in size.
    236 void aom_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_bc,
    237                           YV12_BUFFER_CONFIG *dst_bc, const int num_planes) {
    238  assert(src_bc->y_width == dst_bc->y_width);
    239  assert(src_bc->y_height == dst_bc->y_height);
    240 
    241 #if CONFIG_AV1_HIGHBITDEPTH
    242  assert((src_bc->flags & YV12_FLAG_HIGHBITDEPTH) ==
    243         (dst_bc->flags & YV12_FLAG_HIGHBITDEPTH));
    244 
    245  if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
    246    for (int plane = 0; plane < num_planes; ++plane) {
    247      const uint8_t *plane_src = src_bc->buffers[plane];
    248      uint8_t *plane_dst = dst_bc->buffers[plane];
    249      const int is_uv = plane > 0;
    250 
    251      for (int row = 0; row < src_bc->heights[is_uv]; ++row) {
    252        memcpy_short_addr(plane_dst, plane_src, src_bc->widths[is_uv]);
    253        plane_src += src_bc->strides[is_uv];
    254        plane_dst += dst_bc->strides[is_uv];
    255      }
    256    }
    257    aom_yv12_extend_frame_borders_c(dst_bc, num_planes);
    258    return;
    259  }
    260 #endif
    261  for (int plane = 0; plane < num_planes; ++plane) {
    262    const uint8_t *plane_src = src_bc->buffers[plane];
    263    uint8_t *plane_dst = dst_bc->buffers[plane];
    264    const int is_uv = plane > 0;
    265 
    266    for (int row = 0; row < src_bc->heights[is_uv]; ++row) {
    267      memcpy(plane_dst, plane_src, src_bc->widths[is_uv]);
    268      plane_src += src_bc->strides[is_uv];
    269      plane_dst += dst_bc->strides[is_uv];
    270    }
    271  }
    272  aom_yv12_extend_frame_borders_c(dst_bc, num_planes);
    273 }
    274 
    275 void aom_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
    276                       YV12_BUFFER_CONFIG *dst_ybc, int use_crop) {
    277  int row;
    278  int width = use_crop ? src_ybc->y_crop_width : src_ybc->y_width;
    279  int height = use_crop ? src_ybc->y_crop_height : src_ybc->y_height;
    280  const uint8_t *src = src_ybc->y_buffer;
    281  uint8_t *dst = dst_ybc->y_buffer;
    282 
    283 #if CONFIG_AV1_HIGHBITDEPTH
    284  if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
    285    const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
    286    uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
    287    for (row = 0; row < height; ++row) {
    288      memcpy(dst16, src16, width * sizeof(uint16_t));
    289      src16 += src_ybc->y_stride;
    290      dst16 += dst_ybc->y_stride;
    291    }
    292    return;
    293  }
    294 #endif
    295 
    296  for (row = 0; row < height; ++row) {
    297    memcpy(dst, src, width);
    298    src += src_ybc->y_stride;
    299    dst += dst_ybc->y_stride;
    300  }
    301 }
    302 
    303 void aom_yv12_copy_u_c(const YV12_BUFFER_CONFIG *src_bc,
    304                       YV12_BUFFER_CONFIG *dst_bc, int use_crop) {
    305  int row;
    306  int width = use_crop ? src_bc->uv_crop_width : src_bc->uv_width;
    307  int height = use_crop ? src_bc->uv_crop_height : src_bc->uv_height;
    308  const uint8_t *src = src_bc->u_buffer;
    309  uint8_t *dst = dst_bc->u_buffer;
    310 #if CONFIG_AV1_HIGHBITDEPTH
    311  if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
    312    const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
    313    uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
    314    for (row = 0; row < height; ++row) {
    315      memcpy(dst16, src16, width * sizeof(uint16_t));
    316      src16 += src_bc->uv_stride;
    317      dst16 += dst_bc->uv_stride;
    318    }
    319    return;
    320  }
    321 #endif
    322  for (row = 0; row < height; ++row) {
    323    memcpy(dst, src, width);
    324    src += src_bc->uv_stride;
    325    dst += dst_bc->uv_stride;
    326  }
    327 }
    328 
    329 void aom_yv12_copy_v_c(const YV12_BUFFER_CONFIG *src_bc,
    330                       YV12_BUFFER_CONFIG *dst_bc, int use_crop) {
    331  int row;
    332  int width = use_crop ? src_bc->uv_crop_width : src_bc->uv_width;
    333  int height = use_crop ? src_bc->uv_crop_height : src_bc->uv_height;
    334  const uint8_t *src = src_bc->v_buffer;
    335  uint8_t *dst = dst_bc->v_buffer;
    336 #if CONFIG_AV1_HIGHBITDEPTH
    337  if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
    338    const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
    339    uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
    340    for (row = 0; row < height; ++row) {
    341      memcpy(dst16, src16, width * sizeof(uint16_t));
    342      src16 += src_bc->uv_stride;
    343      dst16 += dst_bc->uv_stride;
    344    }
    345    return;
    346  }
    347 #endif
    348  for (row = 0; row < height; ++row) {
    349    memcpy(dst, src, width);
    350    src += src_bc->uv_stride;
    351    dst += dst_bc->uv_stride;
    352  }
    353 }
    354 
    355 void aom_yv12_partial_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc, int hstart1,
    356                               int hend1, int vstart1, int vend1,
    357                               YV12_BUFFER_CONFIG *dst_ybc, int hstart2,
    358                               int vstart2) {
    359  int row;
    360  const uint8_t *src = src_ybc->y_buffer;
    361  uint8_t *dst = dst_ybc->y_buffer;
    362 #if CONFIG_AV1_HIGHBITDEPTH
    363  if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
    364    const uint16_t *src16 =
    365        CONVERT_TO_SHORTPTR(src + vstart1 * src_ybc->y_stride + hstart1);
    366    uint16_t *dst16 =
    367        CONVERT_TO_SHORTPTR(dst + vstart2 * dst_ybc->y_stride + hstart2);
    368 
    369    for (row = vstart1; row < vend1; ++row) {
    370      memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
    371      src16 += src_ybc->y_stride;
    372      dst16 += dst_ybc->y_stride;
    373    }
    374    return;
    375  }
    376 #endif
    377  src = (src + vstart1 * src_ybc->y_stride + hstart1);
    378  dst = (dst + vstart2 * dst_ybc->y_stride + hstart2);
    379 
    380  for (row = vstart1; row < vend1; ++row) {
    381    memcpy(dst, src, (hend1 - hstart1));
    382    src += src_ybc->y_stride;
    383    dst += dst_ybc->y_stride;
    384  }
    385 }
    386 
    387 void aom_yv12_partial_coloc_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
    388                                     YV12_BUFFER_CONFIG *dst_ybc, int hstart,
    389                                     int hend, int vstart, int vend) {
    390  aom_yv12_partial_copy_y_c(src_ybc, hstart, hend, vstart, vend, dst_ybc,
    391                            hstart, vstart);
    392 }
    393 
    394 void aom_yv12_partial_copy_u_c(const YV12_BUFFER_CONFIG *src_bc, int hstart1,
    395                               int hend1, int vstart1, int vend1,
    396                               YV12_BUFFER_CONFIG *dst_bc, int hstart2,
    397                               int vstart2) {
    398  int row;
    399  const uint8_t *src = src_bc->u_buffer;
    400  uint8_t *dst = dst_bc->u_buffer;
    401 #if CONFIG_AV1_HIGHBITDEPTH
    402  if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
    403    const uint16_t *src16 =
    404        CONVERT_TO_SHORTPTR(src + vstart1 * src_bc->uv_stride + hstart1);
    405    uint16_t *dst16 =
    406        CONVERT_TO_SHORTPTR(dst + vstart2 * dst_bc->uv_stride + hstart2);
    407    for (row = vstart1; row < vend1; ++row) {
    408      memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
    409      src16 += src_bc->uv_stride;
    410      dst16 += dst_bc->uv_stride;
    411    }
    412    return;
    413  }
    414 #endif
    415  src = (src + vstart1 * src_bc->uv_stride + hstart1);
    416  dst = (dst + vstart2 * dst_bc->uv_stride + hstart2);
    417 
    418  for (row = vstart1; row < vend1; ++row) {
    419    memcpy(dst, src, (hend1 - hstart1));
    420    src += src_bc->uv_stride;
    421    dst += dst_bc->uv_stride;
    422  }
    423 }
    424 
    425 void aom_yv12_partial_coloc_copy_u_c(const YV12_BUFFER_CONFIG *src_bc,
    426                                     YV12_BUFFER_CONFIG *dst_bc, int hstart,
    427                                     int hend, int vstart, int vend) {
    428  aom_yv12_partial_copy_u_c(src_bc, hstart, hend, vstart, vend, dst_bc, hstart,
    429                            vstart);
    430 }
    431 
    432 void aom_yv12_partial_copy_v_c(const YV12_BUFFER_CONFIG *src_bc, int hstart1,
    433                               int hend1, int vstart1, int vend1,
    434                               YV12_BUFFER_CONFIG *dst_bc, int hstart2,
    435                               int vstart2) {
    436  int row;
    437  const uint8_t *src = src_bc->v_buffer;
    438  uint8_t *dst = dst_bc->v_buffer;
    439 #if CONFIG_AV1_HIGHBITDEPTH
    440  if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
    441    const uint16_t *src16 =
    442        CONVERT_TO_SHORTPTR(src + vstart1 * src_bc->uv_stride + hstart1);
    443    uint16_t *dst16 =
    444        CONVERT_TO_SHORTPTR(dst + vstart2 * dst_bc->uv_stride + hstart2);
    445    for (row = vstart1; row < vend1; ++row) {
    446      memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
    447      src16 += src_bc->uv_stride;
    448      dst16 += dst_bc->uv_stride;
    449    }
    450    return;
    451  }
    452 #endif
    453  src = (src + vstart1 * src_bc->uv_stride + hstart1);
    454  dst = (dst + vstart2 * dst_bc->uv_stride + hstart2);
    455 
    456  for (row = vstart1; row < vend1; ++row) {
    457    memcpy(dst, src, (hend1 - hstart1));
    458    src += src_bc->uv_stride;
    459    dst += dst_bc->uv_stride;
    460  }
    461 }
    462 
    463 void aom_yv12_partial_coloc_copy_v_c(const YV12_BUFFER_CONFIG *src_bc,
    464                                     YV12_BUFFER_CONFIG *dst_bc, int hstart,
    465                                     int hend, int vstart, int vend) {
    466  aom_yv12_partial_copy_v_c(src_bc, hstart, hend, vstart, vend, dst_bc, hstart,
    467                            vstart);
    468 }
    469 
    470 int aom_yv12_realloc_with_new_border_c(YV12_BUFFER_CONFIG *ybf, int new_border,
    471                                       int byte_alignment, bool alloc_pyramid,
    472                                       int num_planes) {
    473  if (ybf) {
    474    if (new_border == ybf->border) return 0;
    475    YV12_BUFFER_CONFIG new_buf;
    476    memset(&new_buf, 0, sizeof(new_buf));
    477    const int error = aom_alloc_frame_buffer(
    478        &new_buf, ybf->y_crop_width, ybf->y_crop_height, ybf->subsampling_x,
    479        ybf->subsampling_y, ybf->flags & YV12_FLAG_HIGHBITDEPTH, new_border,
    480        byte_alignment, alloc_pyramid, 0);
    481    if (error) return error;
    482    // Copy image buffer
    483    aom_yv12_copy_frame(ybf, &new_buf, num_planes);
    484 
    485    // Extend up to new border
    486    aom_extend_frame_borders(&new_buf, num_planes);
    487 
    488    // Now free the old buffer and replace with the new
    489    aom_free_frame_buffer(ybf);
    490    *ybf = new_buf;
    491    return 0;
    492  }
    493  return -2;
    494 }