// Allocate storage for each tile column. // TODO(jzern): when max_threads <= 1 the same storage could be used for each // tile. static void alloc_tile_storage(VP9D_COMP *pbi, int tile_cols) { VP9_COMMON *const cm = &pbi->common; const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols); int i, tile_col; CHECK_MEM_ERROR(cm, pbi->mi_streams, vpx_realloc(pbi->mi_streams, tile_cols * sizeof(*pbi->mi_streams))); for (tile_col = 0; tile_col < tile_cols; ++tile_col) { TileInfo tile; vp9_tile_init(&tile, cm, 0, tile_col); pbi->mi_streams[tile_col] = &cm->mi[cm->mi_rows * tile.mi_col_start]; } // 2 contexts per 'mi unit', so that we have one context per 4x4 txfm // block where mi unit size is 8x8. CHECK_MEM_ERROR(cm, pbi->above_context[0], vpx_realloc(pbi->above_context[0], sizeof(*pbi->above_context[0]) * MAX_MB_PLANE * 2 * aligned_mi_cols)); for (i = 1; i < MAX_MB_PLANE; ++i) { pbi->above_context[i] = pbi->above_context[0] + i * sizeof(*pbi->above_context[0]) * 2 * aligned_mi_cols; } // This is sized based on the entire frame. Each tile operates within its // column bounds. CHECK_MEM_ERROR(cm, pbi->above_seg_context, vpx_realloc(pbi->above_seg_context, sizeof(*pbi->above_seg_context) * aligned_mi_cols)); }
int vp9_get_frame_buffer(void *cb_priv, size_t min_size, vpx_codec_frame_buffer_t *fb) { int i; InternalFrameBufferList *const int_fb_list = (InternalFrameBufferList *)cb_priv; if (int_fb_list == NULL) return -1; // Find a free frame buffer. for (i = 0; i < int_fb_list->num_internal_frame_buffers; ++i) { if (!int_fb_list->int_fb[i].in_use) break; } if (i == int_fb_list->num_internal_frame_buffers) return -1; if (int_fb_list->int_fb[i].size < min_size) { int_fb_list->int_fb[i].data = (uint8_t *)vpx_realloc(int_fb_list->int_fb[i].data, min_size); if (!int_fb_list->int_fb[i].data) return -1; int_fb_list->int_fb[i].size = min_size; } fb->data = int_fb_list->int_fb[i].data; fb->size = int_fb_list->int_fb[i].size; int_fb_list->int_fb[i].in_use = 1; // Set the frame buffer's private data to point at the internal frame buffer. fb->priv = &int_fb_list->int_fb[i]; return 0; }
int vp10_get_frame_buffer(void *cb_priv, size_t min_size, vpx_codec_frame_buffer_t *fb) { int i; InternalFrameBufferList *const int_fb_list = (InternalFrameBufferList *)cb_priv; if (int_fb_list == NULL) return -1; // Find a free frame buffer. for (i = 0; i < int_fb_list->num_internal_frame_buffers; ++i) { if (!int_fb_list->int_fb[i].in_use) break; } if (i == int_fb_list->num_internal_frame_buffers) return -1; if (int_fb_list->int_fb[i].size < min_size) { int_fb_list->int_fb[i].data = (uint8_t *)vpx_realloc(int_fb_list->int_fb[i].data, min_size); if (!int_fb_list->int_fb[i].data) return -1; // This memset is needed for fixing valgrind error from C loop filter // due to access uninitialized memory in frame border. It could be // removed if border is totally removed. memset(int_fb_list->int_fb[i].data, 0, min_size); int_fb_list->int_fb[i].size = min_size; } fb->data = int_fb_list->int_fb[i].data; fb->size = int_fb_list->int_fb[i].size; int_fb_list->int_fb[i].in_use = 1; // Set the frame buffer's private data to point at the internal frame buffer. fb->priv = &int_fb_list->int_fb[i]; return 0; }
static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, const uint8_t **data, unsigned int data_sz, void *user_priv, int64_t deadline) { const VPxWorkerInterface *const winterface = vpx_get_worker_interface(); (void)deadline; // Determine the stream parameters. Note that we rely on peek_si to // validate that we have a buffer that does not wrap around the top // of the heap. if (!ctx->si.h) { int is_intra_only = 0; const vpx_codec_err_t res = decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only, ctx->decrypt_cb, ctx->decrypt_state); if (res != VPX_CODEC_OK) return res; if (!ctx->si.is_kf && !is_intra_only) return VPX_CODEC_ERROR; } if (!ctx->frame_parallel_decode) { VPxWorker *const worker = ctx->frame_workers; FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; frame_worker_data->data = *data; frame_worker_data->data_size = data_sz; frame_worker_data->user_priv = user_priv; frame_worker_data->received_frame = 1; // Set these even if already initialized. The caller may have changed the // decrypt config between frames. frame_worker_data->pbi->decrypt_cb = ctx->decrypt_cb; frame_worker_data->pbi->decrypt_state = ctx->decrypt_state; worker->had_error = 0; winterface->execute(worker); // Update data pointer after decode. *data = frame_worker_data->data_end; if (worker->had_error) return update_error_state(ctx, &frame_worker_data->pbi->common.error); check_resync(ctx, frame_worker_data->pbi); } else { VPxWorker *const worker = &ctx->frame_workers[ctx->next_submit_worker_id]; FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; // Copy context from last worker thread to next worker thread. if (ctx->next_submit_worker_id != ctx->last_submit_worker_id) vp9_frameworker_copy_context( &ctx->frame_workers[ctx->next_submit_worker_id], &ctx->frame_workers[ctx->last_submit_worker_id]); frame_worker_data->pbi->ready_for_new_data = 0; // Copy the compressed data into worker's internal buffer. // TODO(hkuang): Will all the workers allocate the same size // as the size of the first intra frame be better? This will // avoid too many deallocate and allocate. if (frame_worker_data->scratch_buffer_size < data_sz) { frame_worker_data->scratch_buffer = (uint8_t *)vpx_realloc(frame_worker_data->scratch_buffer, data_sz); if (frame_worker_data->scratch_buffer == NULL) { set_error_detail(ctx, "Failed to reallocate scratch buffer"); return VPX_CODEC_MEM_ERROR; } frame_worker_data->scratch_buffer_size = data_sz; } frame_worker_data->data_size = data_sz; memcpy(frame_worker_data->scratch_buffer, *data, data_sz); frame_worker_data->frame_decoded = 0; frame_worker_data->frame_context_ready = 0; frame_worker_data->received_frame = 1; frame_worker_data->data = frame_worker_data->scratch_buffer; frame_worker_data->user_priv = user_priv; if (ctx->next_submit_worker_id != ctx->last_submit_worker_id) ctx->last_submit_worker_id = (ctx->last_submit_worker_id + 1) % ctx->num_frame_workers; ctx->next_submit_worker_id = (ctx->next_submit_worker_id + 1) % ctx->num_frame_workers; --ctx->available_threads; worker->had_error = 0; winterface->launch(worker); } return VPX_CODEC_OK; }