static vpx_codec_err_t vp9_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline) { const uint8_t *data_start = data; const uint8_t *data_end = data + data_sz; vpx_codec_err_t res; do { res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); assert(data_start >= data); assert(data_start <= data_end); /* Early exit if there was a decode error */ if (res) break; /* Account for suboptimal termination by the encoder. */ while (data_start < data_end && *data_start == 0) data_start++; data_sz = data_end - data_start; } while (data_start < data_end); return res; }
static vpx_codec_err_t vp9_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline) { const uint8_t *data_start = data; const uint8_t *data_end = data + data_sz; vpx_codec_err_t res = 0; uint32_t sizes[8]; int frames_this_pts, frame_count = 0; parse_superframe_index(data, data_sz, sizes, &frames_this_pts); do { // Skip over the superframe index, if present if (data_sz && (*data_start & 0xe0) == 0xc0) { const uint8_t marker = *data_start; const uint32_t frames = (marker & 0x7) + 1; const uint32_t mag = ((marker >> 3) & 0x3) + 1; const uint32_t index_sz = 2 + mag * frames; if (data_sz >= index_sz && data_start[index_sz - 1] == marker) { data_start += index_sz; data_sz -= index_sz; if (data_start < data_end) continue; else break; } } // Use the correct size for this frame, if an index is present. if (frames_this_pts) { uint32_t this_sz = sizes[frame_count]; if (data_sz < this_sz) { ctx->base.err_detail = "Invalid frame size in index"; return VPX_CODEC_CORRUPT_FRAME; } data_sz = this_sz; frame_count++; } res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); assert(data_start >= data); assert(data_start <= data_end); /* Early exit if there was a decode error */ if (res) break; /* Account for suboptimal termination by the encoder. */ while (data_start < data_end && *data_start == 0) data_start++; data_sz = data_end - data_start; } while (data_start < data_end); return res; }
/** * Decodes the input file to the output file. * * Returns the number of bytes decoded. */ int decoder_decode(Decoder *decoder) { assert(decoder != NULL); // Read characters: int ch; while ((ch = decode_one(decoder)) != -1) { fprintf(decoder->outfp, "%c", ch); } // Return the number of bytes written: return bits_io_num_bytes(decoder->bfile); }
huffman_error huffman_8bit_decoder::decode(const UINT8 *source, UINT32 slength, UINT8 *dest, UINT32 dlength) { // first import the tree bitstream_in bitbuf(source, slength); huffman_error err = import_tree_huffman(bitbuf); if (err != HUFFERR_NONE) return err; // then decode the data for (UINT32 cur = 0; cur < dlength; cur++) dest[cur] = decode_one(bitbuf); bitbuf.flush(); return bitbuf.overflow() ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE; }
static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx, const uint8_t **data_start_ptr, const uint8_t *data_end, uint32_t frame_size, void *user_priv, long deadline) { const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size, user_priv, deadline); if (res != VPX_CODEC_OK) return res; // Account for suboptimal termination by the encoder. while (*data_start_ptr < data_end) { const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, *data_start_ptr); if (marker) break; (*data_start_ptr)++; } return VPX_CODEC_OK; }
static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline) { const uint8_t *data_start = data; const uint8_t * const data_end = data + data_sz; vpx_codec_err_t res; uint32_t frame_sizes[8]; int frame_count; if (data == NULL && data_sz == 0) { ctx->flushed = 1; return VPX_CODEC_OK; } // Reset flushed when receiving a valid frame. ctx->flushed = 0; // Initialize the decoder workers on the first frame. if (ctx->frame_workers == NULL) { const vpx_codec_err_t res = init_decoder(ctx); if (res != VPX_CODEC_OK) return res; } res = vp9_parse_superframe_index(data, data_sz, frame_sizes, &frame_count, ctx->decrypt_cb, ctx->decrypt_state); if (res != VPX_CODEC_OK) return res; if (ctx->frame_parallel_decode) { // Decode in frame parallel mode. When decoding in this mode, the frame // passed to the decoder must be either a normal frame or a superframe with // superframe index so the decoder could get each frame's start position // in the superframe. if (frame_count > 0) { int i; for (i = 0; i < frame_count; ++i) { const uint8_t *data_start_copy = data_start; const uint32_t frame_size = frame_sizes[i]; if (data_start < data || frame_size > (uint32_t) (data_end - data_start)) { set_error_detail(ctx, "Invalid frame size in index"); return VPX_CODEC_CORRUPT_FRAME; } if (ctx->available_threads == 0) { // No more threads for decoding. Wait until the next output worker // finishes decoding. Then copy the decoded frame into cache. if (ctx->num_cache_frames < FRAME_CACHE_SIZE) { wait_worker_and_cache_frame(ctx); } else { // TODO(hkuang): Add unit test to test this path. set_error_detail(ctx, "Frame output cache is full."); return VPX_CODEC_ERROR; } } res = decode_one(ctx, &data_start_copy, frame_size, user_priv, deadline); if (res != VPX_CODEC_OK) return res; data_start += frame_size; } } else { if (ctx->available_threads == 0) { // No more threads for decoding. Wait until the next output worker // finishes decoding. Then copy the decoded frame into cache. if (ctx->num_cache_frames < FRAME_CACHE_SIZE) { wait_worker_and_cache_frame(ctx); } else { // TODO(hkuang): Add unit test to test this path. set_error_detail(ctx, "Frame output cache is full."); return VPX_CODEC_ERROR; } } res = decode_one(ctx, &data, data_sz, user_priv, deadline); if (res != VPX_CODEC_OK) return res; } } else { // Decode in serial mode. if (frame_count > 0) { int i; for (i = 0; i < frame_count; ++i) { const uint8_t *data_start_copy = data_start; const uint32_t frame_size = frame_sizes[i]; vpx_codec_err_t res; if (data_start < data || frame_size > (uint32_t) (data_end - data_start)) { set_error_detail(ctx, "Invalid frame size in index"); return VPX_CODEC_CORRUPT_FRAME; } res = decode_one(ctx, &data_start_copy, frame_size, user_priv, deadline); if (res != VPX_CODEC_OK) return res; data_start += frame_size; } } else { while (data_start < data_end) { const uint32_t frame_size = (uint32_t) (data_end - data_start); const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size, user_priv, deadline); if (res != VPX_CODEC_OK) return res; // Account for suboptimal termination by the encoder. while (data_start < data_end) { const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, data_start); if (marker) break; ++data_start; } } } } return res; }