Пример #1
0
static bool input_context_FILE_read(input_context* ctx)
{
  input_context_FILE* filectx = (input_context_FILE*)ctx;

  int free_space = ctx->input_buffer.capacity - ctx->input_buffer.size;
  int read_chunk_size;

  if (free_space < READ_CHUNK_SIZE) {
    int new_size = ctx->input_buffer.capacity + READ_CHUNK_SIZE;
    rbsp_buffer_resize(&ctx->input_buffer, new_size);
    read_chunk_size = ctx->input_buffer.capacity - ctx->input_buffer.size;
  } else {
    read_chunk_size = free_space;
  }

  int nread = fread(&ctx->input_buffer.data[ctx->input_buffer.size],
                    1,read_chunk_size,
                    filectx->input_file);

  if (nread==0) {
    return false;
  } else {
    ctx->input_buffer.size += nread;
    return true;
  }
}
Пример #2
0
LIBDE265_API de265_error de265_push_NAL(de265_decoder_context* de265ctx,
                                        const void* data8, int len,
                                        de265_PTS pts, void* user_data)
{
  decoder_context* ctx = (decoder_context*)de265ctx;
  uint8_t* data = (uint8_t*)data8;

  // Cannot use byte-stream input and NAL input at the same time.
  assert(ctx->pending_input_NAL == NULL);

  NAL_unit* nal = alloc_NAL_unit(ctx, len, DE265_SKIPPED_BYTES_INITIAL_SIZE);
  rbsp_buffer_resize(&nal->nal_data, len);
  nal->nal_data.size = len;
  nal->pts = pts;
  nal->user_data = user_data;
  memcpy(nal->nal_data.data, data, len);

  remove_stuffing_bytes(nal);

  push_to_NAL_queue(ctx, nal);

  return DE265_OK;
}
Пример #3
0
static de265_error process_data(decoder_context* ctx, const uint8_t* data, int len,
                                int* out_nBytesProcessed)
{
  *out_nBytesProcessed=0;

  /*
  printf("len=%d\n",len);

  for (int i=0;i<16;i++) {
    printf("%02x ",data[i]);
  }
  printf("\n");
  */

  // Resize output buffer so that complete input would fit.
  // We add 3, because in the worst case 3 extra bytes are created for an input byte.
  rbsp_buffer_resize(&ctx->nal_data, ctx->nal_data.size + len + 3);

  unsigned char* out = ctx->nal_data.data + ctx->nal_data.size;

  for (int i=0;i<len;i++) {
    (*out_nBytesProcessed)++;

    /*
    printf("state=%d input=%02x (%p) (output size: %d)\n",ctx->input_push_state, *data, data,
           out - ctx->nal_data.data);
    */

    switch (ctx->input_push_state) {
    case 0:
    case 1:
      if (*data == 0) { ctx->input_push_state++; }
      else { return DE265_ERROR_NO_STARTCODE; }
      break;
    case 2:
      if      (*data == 1) { ctx->input_push_state=3; ctx->num_skipped_bytes=0; }
      else if (*data == 0) { } // *out++ = 0; }
      else { return DE265_ERROR_NO_STARTCODE; }
      break;
    case 3:
      /*
      *out++ = 0;
      *out++ = 0;
      *out++ = 1;
      */
      *out++ = *data;
      ctx->input_push_state = 4;
      break;
    case 4:
      *out++ = *data;
      ctx->input_push_state = 5;
      break;

    case 5:
      if (*data==0) { ctx->input_push_state=6; }
      else { *out++ = *data; }
      break;

    case 6:
      if (*data==0) { ctx->input_push_state=7; }
      else {
        *out++ = 0;
        *out++ = *data;
        ctx->input_push_state=5;
      }
      break;

    case 7:
      if      (*data==0) { *out++ = 0; }
      else if (*data==3) {
        *out++ = 0; *out++ = 0; ctx->input_push_state=5;

        // remember which byte we removed

        int* skipped = (int *)malloc((ctx->num_skipped_bytes+1) * sizeof(int));

        if (ctx->num_skipped_bytes>0) {
          memcpy(skipped, ctx->skipped_bytes, ctx->num_skipped_bytes * sizeof(int));
        }

        if (ctx->skipped_bytes) {
          free(ctx->skipped_bytes);
        }

        skipped[ctx->num_skipped_bytes] = (out - ctx->nal_data.data) + ctx->num_skipped_bytes;

        ctx->skipped_bytes = skipped;

        ctx->num_skipped_bytes++;
      }
      else if (*data==1) {

        // decode this NAL
        ctx->nal_data.size = out - ctx->nal_data.data;
        de265_error err = de265_decode_NAL((de265_decoder_context*)ctx, &ctx->nal_data);

        // clear buffer for next NAL
        ctx->nal_data.size = 0;
        out = ctx->nal_data.data;

        ctx->input_push_state=3;
        ctx->num_skipped_bytes=0;

        if (err != DE265_OK) {
          data++;
          return err;
        }

        // when there are no free image buffers in the DPB, pause decoding
        if (!has_free_dpb_picture(ctx)) {
          data++;
          return err;
        }
      }
      else {
        *out++ = 0;
        *out++ = 0;
        *out++ = *data;

        ctx->input_push_state=5;
      }
      break;
    }

    data++;

    /*
    for (int i=0;i<out - ctx->nal_data.data;i++) {
      printf("%02x ",ctx->nal_data.data[i]);
    }
    printf("\n");
    */
  }


  if (*out_nBytesProcessed == len && ctx->end_of_stream &&
      ctx->input_push_state != 8) {
    if      (ctx->input_push_state<5) { return DE265_ERROR_EOF; }
    else if (ctx->input_push_state==6) { *out++ = 0; }
    else if (ctx->input_push_state==7) { *out++ = 0; *out++ = 0; }

    ctx->input_push_state=8; // end of stream, stop all processing

    // decode data
    ctx->nal_data.size = out - ctx->nal_data.data;
    de265_error err = de265_decode_NAL((de265_decoder_context*)ctx, &ctx->nal_data);
    if (err != DE265_OK) {
      return err;
    }

    push_current_picture_to_output_queue(ctx);

    // clear buffer
    ctx->nal_data.size = 0;
    out = ctx->nal_data.data;

    return DE265_OK;
  }


  ctx->nal_data.size = out - ctx->nal_data.data;
  return DE265_OK;
}
Пример #4
0
void rbsp_buffer_append(rbsp_buffer* buffer, const unsigned char* data, int n)
{
  rbsp_buffer_resize(buffer, buffer->size + n);
  memcpy(buffer->data + buffer->size, data, n);
  buffer->size += n;
}
Пример #5
0
int read_nal_unit(input_context* ctx, rbsp_buffer* buffer)
{
  buffer->size=0;

  // if there is not even a NAL header remaining in the input, we are at EOF

  if (ctx->input_buffer.size < 4+2) {
    bool more_data = ctx->refill_buffer(ctx);
    if (!more_data || ctx->input_buffer.size < 4+2) {
      return DE265_ERROR_EOF;
    }
  }

  // reserve enough space so that complete input would fit into output buffer
  rbsp_buffer_resize(buffer, ctx->input_buffer.size);


  unsigned char* out = buffer->data;
  int in_idx =0;
  int out_idx=0;

  // check for start-code at the beginning

  unsigned char* in = ctx->input_buffer.data;
  while (in[in_idx+0]==0 && in[in_idx+1]==0 && in[in_idx+2]==0) {
    in_idx++;
    if (ctx->input_buffer.size < in_idx+4+2) {
      return DE265_ERROR_EOF;
    }
  }

  if (in[in_idx+0] != 0 || in[in_idx+1] != 0 || in[in_idx+2] != 1) {
    return DE265_ERROR_NO_STARTCODE;
  }

  in_idx+=3;


  // copy NAL header
  out[out_idx++] = in[in_idx++];
  out[out_idx++] = in[in_idx++];


  // copy until next start-code (removing start-code emulation prevention bytes)

  for (;;) {
    // when we approach the end of the input buffer, resize (both) buffers

    if (ctx->input_buffer.size < in_idx+4) {
      bool more_data = ctx->refill_buffer(ctx);
      in = ctx->input_buffer.data;

      if (!more_data) {
        assert(ctx->input_buffer.size - in_idx < 4);
        buffer->size = out_idx;
        rbsp_buffer_resize(buffer, buffer->size+4);  // space for up to 4 more bytes
        out = buffer->data;

        // copy remaining data to output

        while (in_idx < ctx->input_buffer.size) {
          out[out_idx++] = in[in_idx++];
        }

        ctx->input_buffer.size = 0; // we read all data
        buffer->size = out_idx;

        return DE265_OK;
      }

      // make space such that all input data would possibly fit into the output

      int remaining_input_data = ctx->input_buffer.size - in_idx;
      buffer->size = out_idx;
      rbsp_buffer_resize(buffer, buffer->size + remaining_input_data);
      out = buffer->data;
    }

    // check for next start-code
    if (in[in_idx+0]==0 && in[in_idx+1]==0 && in[in_idx+2]==1) {

      // remove read data from input buffer

      memmove(ctx->input_buffer.data, ctx->input_buffer.data + in_idx,
              ctx->input_buffer.size - in_idx);

      ctx->input_buffer.size -= in_idx;
      buffer->size = out_idx;

      return DE265_OK;
    }

    // check for start-code emulation
    if (in[in_idx+0]==0 && in[in_idx+1]==0 && in[in_idx+2]==3) {
      assert(out_idx+2 <= buffer->capacity);
      out[out_idx++] = in[in_idx++];
      out[out_idx++] = in[in_idx++];
      in_idx++; // skip start-code emulation byte
    } else {
      assert(out_idx+1 <= buffer->capacity);
      out[out_idx++] = in[in_idx++];
    }
  }
}
Пример #6
0
LIBDE265_API de265_error de265_push_data(de265_decoder_context* de265ctx,
                                         const void* data8, int len,
                                         de265_PTS pts, void* user_data)
{
  decoder_context* ctx = (decoder_context*)de265ctx;
  uint8_t* data = (uint8_t*)data8;

  if (ctx->pending_input_NAL == NULL) {
    ctx->pending_input_NAL = alloc_NAL_unit(ctx, len+3, DE265_SKIPPED_BYTES_INITIAL_SIZE);
    ctx->pending_input_NAL->pts = pts;
    ctx->pending_input_NAL->user_data = user_data;
  }

  NAL_unit* nal = ctx->pending_input_NAL; // shortcut

  // Resize output buffer so that complete input would fit.
  // We add 3, because in the worst case 3 extra bytes are created for an input byte.
  rbsp_buffer_resize(&nal->nal_data, nal->nal_data.size + len + 3);

  unsigned char* out = nal->nal_data.data + nal->nal_data.size;

  for (int i=0;i<len;i++) {
    /*
    printf("state=%d input=%02x (%p) (output size: %d)\n",ctx->input_push_state, *data, data,
           out - ctx->nal_data.data);
    */

    switch (ctx->input_push_state) {
    case 0:
    case 1:
      if (*data == 0) { ctx->input_push_state++; }
      else { ctx->input_push_state=0; }
      break;
    case 2:
      if      (*data == 1) { ctx->input_push_state=3; nal->num_skipped_bytes=0; }
      else if (*data == 0) { } // *out++ = 0; }
      else { ctx->input_push_state=0; }
      break;
    case 3:
      *out++ = *data;
      ctx->input_push_state = 4;
      break;
    case 4:
      *out++ = *data;
      ctx->input_push_state = 5;
      break;

    case 5:
      if (*data==0) { ctx->input_push_state=6; }
      else { *out++ = *data; }
      break;

    case 6:
      if (*data==0) { ctx->input_push_state=7; }
      else {
        *out++ = 0;
        *out++ = *data;
        ctx->input_push_state=5;
      }
      break;

    case 7:
      if      (*data==0) { *out++ = 0; }
      else if (*data==3) {
        *out++ = 0; *out++ = 0; ctx->input_push_state=5;

        // remember which byte we removed
        nal_insert_skipped_byte(nal, (out - nal->nal_data.data) + nal->num_skipped_bytes);
      }
      else if (*data==1) {

#if DEBUG_INSERT_STREAM_ERRORS
        if ((rand()%100)<90 && ctx->nal_data.size>0) {
          int pos = rand()%ctx->nal_data.size;
          int bit = rand()%8;
          nal->nal_data.data[pos] ^= 1<<bit;

          //printf("inserted error...\n");
        }
#endif

        nal->nal_data.size = out - nal->nal_data.data;

        // push this NAL decoder queue
        push_to_NAL_queue(ctx, nal);


        // initialize new, empty NAL unit

        ctx->pending_input_NAL = alloc_NAL_unit(ctx, len+3, DE265_SKIPPED_BYTES_INITIAL_SIZE);
        ctx->pending_input_NAL->pts = pts;
        nal = ctx->pending_input_NAL;
        out = nal->nal_data.data;

        ctx->input_push_state=3;
        nal->num_skipped_bytes=0;
      }
      else {
        *out++ = 0;
        *out++ = 0;
        *out++ = *data;

        ctx->input_push_state=5;
      }
      break;
    }

    data++;
  }

  nal->nal_data.size = out - nal->nal_data.data;
  return DE265_OK;
}