Make the api behavior conform to api spec.

When no more data is available, vpx_codec_decode should
be called with NULL as data and 0 as data_sz.

vpx_codec_get_frame iterates over a list of the frames
available for display. The iterator storage should be initialized
to NULL to start the iteration. Iteration is complete when this
function returns NULL.

Also change the unit test to conform to the api spec.

Change-Id: I4b258b309f5df3d37d10c82f01492c0394181c2a
This commit is contained in:
Hangyu Kuang 2014-07-31 19:04:35 -07:00
parent f94227c81d
commit 7050074756
3 changed files with 37 additions and 12 deletions

View File

@ -67,24 +67,33 @@ void DecoderTest::RunLoop(CompressedVideoSource *video,
const vpx_codec_dec_cfg_t &dec_cfg) {
Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0);
ASSERT_TRUE(decoder != NULL);
bool end_of_file = false;
// Decode frames.
for (video->Begin(); !::testing::Test::HasFailure() && video->cxdata();
for (video->Begin(); !::testing::Test::HasFailure() && !end_of_file;
video->Next()) {
PreDecodeFrameHook(*video, decoder);
vpx_codec_stream_info_t stream_info;
stream_info.sz = sizeof(stream_info);
const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
video->frame_size(),
&stream_info);
HandlePeekResult(decoder, video, res_peek);
ASSERT_FALSE(::testing::Test::HasFailure());
vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
video->frame_size());
if (!HandleDecodeResult(res_dec, *video, decoder))
break;
if (video->cxdata() != NULL) {
const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
video->frame_size(),
&stream_info);
HandlePeekResult(decoder, video, res_peek);
ASSERT_FALSE(::testing::Test::HasFailure());
vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
video->frame_size());
if (!HandleDecodeResult(res_dec, *video, decoder))
break;
} else {
// Signal end of the file to the decoder.
const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
end_of_file = true;
}
DxDataIterator dec_iter = decoder->GetDxData();
const vpx_image_t *img = NULL;

View File

@ -60,6 +60,7 @@ struct vpx_codec_alg_priv
vpx_decrypt_cb decrypt_cb;
void *decrypt_state;
vpx_image_t img;
int flushed;
int img_setup;
struct frame_buffers yv12_frame_buffers;
void *user_priv;
@ -88,6 +89,7 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx)
ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
ctx->priv->alg_priv->decrypt_cb = NULL;
ctx->priv->alg_priv->decrypt_state = NULL;
ctx->priv->alg_priv->flushed = 0;
ctx->priv->init_flags = ctx->init_flags;
if (ctx->config.dec)
@ -328,6 +330,13 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
unsigned int resolution_change = 0;
unsigned int w, h;
if (data == NULL && data_sz == 0) {
ctx->flushed = 1;
return VPX_CODEC_OK;
}
/* Reset flushed when receiving a valid frame */
ctx->flushed = 0;
/* Update the input fragment data */
if(update_fragments(ctx, data, data_sz, &res) <= 0)

View File

@ -40,6 +40,7 @@ struct vpx_codec_alg_priv {
void *decrypt_state;
vpx_image_t img;
int img_avail;
int flushed;
int invert_tile_order;
int frame_parallel_decode; // frame-based threading.
@ -69,6 +70,7 @@ static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
ctx->priv->alg_priv = alg_priv;
ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
ctx->priv->init_flags = ctx->init_flags;
ctx->priv->alg_priv->flushed = 0;
ctx->priv->alg_priv->frame_parallel_decode =
(ctx->init_flags & VPX_CODEC_USE_FRAME_THREADING);
@ -403,8 +405,13 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
uint32_t frame_sizes[8];
int frame_count;
if (data == NULL || data_sz == 0)
return VPX_CODEC_INVALID_PARAM;
if (data == NULL && data_sz == 0) {
ctx->flushed = 1;
return VPX_CODEC_OK;
}
// Reset flushed when receiving a valid frame.
ctx->flushed = 0;
res = parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
ctx->decrypt_cb, ctx->decrypt_state);