| Index: source/libvpx/test/svc_test.cc
|
| ===================================================================
|
| --- source/libvpx/test/svc_test.cc (revision 291857)
|
| +++ source/libvpx/test/svc_test.cc (working copy)
|
| @@ -60,7 +60,7 @@
|
| codec_enc_.kf_min_dist = 100;
|
| codec_enc_.kf_max_dist = 100;
|
|
|
| - vpx_codec_dec_cfg_t dec_cfg = {0};
|
| + vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
|
| VP9CodecFactory codec_factory;
|
| decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
|
| }
|
| @@ -112,7 +112,7 @@
|
| video.Next();
|
| }
|
|
|
| - // Flush encoder and test EOS packet
|
| + // Flush encoder and test EOS packet.
|
| res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
|
| video.duration(), VPX_DL_GOOD_QUALITY);
|
| stats_size = vpx_svc_get_rc_stats_buffer_size(&svc_);
|
| @@ -135,7 +135,7 @@
|
| EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
|
| }
|
|
|
| - outputs[*frame_received].buf = malloc(frame_size);
|
| + outputs[*frame_received].buf = malloc(frame_size + 16);
|
| ASSERT_TRUE(outputs[*frame_received].buf != NULL);
|
| memcpy(outputs[*frame_received].buf, vpx_svc_get_buffer(&svc_),
|
| frame_size);
|
| @@ -176,13 +176,13 @@
|
| video.Next();
|
| }
|
|
|
| - // Flush Encoder
|
| + // Flush encoder.
|
| res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
|
| video.duration(), VPX_DL_GOOD_QUALITY);
|
| EXPECT_EQ(VPX_CODEC_OK, res);
|
| StoreFrames(n, outputs, &frame_received);
|
|
|
| - EXPECT_EQ(frame_received, (size_t)n);
|
| + EXPECT_EQ(frame_received, static_cast<size_t>(n));
|
|
|
| ReleaseEncoder();
|
| }
|
| @@ -204,7 +204,7 @@
|
| ++decoded_frames;
|
|
|
| DxDataIterator dec_iter = decoder_->GetDxData();
|
| - while (dec_iter.Next()) {
|
| + while (dec_iter.Next() != NULL) {
|
| ++received_frames;
|
| }
|
| }
|
| @@ -212,12 +212,13 @@
|
| EXPECT_EQ(received_frames, n);
|
| }
|
|
|
| - void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
|
| - const int num_super_frames,
|
| - const int remained_layers) {
|
| + void DropLayersAndMakeItVP9Comaptible(struct vpx_fixed_buf *const inputs,
|
| + const int num_super_frames,
|
| + const int remained_spatial_layers,
|
| + const bool is_multiple_frame_contexts) {
|
| ASSERT_TRUE(inputs != NULL);
|
| ASSERT_GT(num_super_frames, 0);
|
| - ASSERT_GT(remained_layers, 0);
|
| + ASSERT_GT(remained_spatial_layers, 0);
|
|
|
| for (int i = 0; i < num_super_frames; ++i) {
|
| uint32_t frame_sizes[8] = {0};
|
| @@ -233,34 +234,112 @@
|
| NULL, NULL);
|
| ASSERT_EQ(VPX_CODEC_OK, res);
|
|
|
| - uint8_t *frame_data = static_cast<uint8_t *>(inputs[i].buf);
|
| - uint8_t *frame_start = frame_data;
|
| - for (frame = 0; frame < frame_count; ++frame) {
|
| - // Looking for a visible frame
|
| - if (frame_data[0] & 0x02) {
|
| - ++frames_found;
|
| - if (frames_found == remained_layers)
|
| - break;
|
| + if (frame_count == 0) {
|
| + // There's no super frame but only a single frame.
|
| + ASSERT_EQ(1, remained_spatial_layers);
|
| + if (is_multiple_frame_contexts) {
|
| + // Make a new super frame.
|
| + uint8_t marker = 0xc1;
|
| + unsigned int mask;
|
| + int mag;
|
| +
|
| + // Choose the magnitude.
|
| + for (mag = 0, mask = 0xff; mag < 4; ++mag) {
|
| + if (inputs[i].sz < mask)
|
| + break;
|
| + mask <<= 8;
|
| + mask |= 0xff;
|
| + }
|
| + marker |= mag << 3;
|
| + int index_sz = 2 + (mag + 1) * 2;
|
| +
|
| + inputs[i].buf = realloc(inputs[i].buf, inputs[i].sz + index_sz + 16);
|
| + ASSERT_TRUE(inputs[i].buf != NULL);
|
| + uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
|
| + frame_data[0] &= ~2; // Set the show_frame flag to 0.
|
| + frame_data += inputs[i].sz;
|
| + // Add an one byte frame with show_existing_frame.
|
| + *frame_data++ = 0x88;
|
| +
|
| + // Write the super frame index.
|
| + *frame_data++ = marker;
|
| +
|
| + frame_sizes[0] = inputs[i].sz;
|
| + frame_sizes[1] = 1;
|
| + for (int j = 0; j < 2; ++j) {
|
| + unsigned int this_sz = frame_sizes[j];
|
| + for (int k = 0; k <= mag; k++) {
|
| + *frame_data++ = this_sz & 0xff;
|
| + this_sz >>= 8;
|
| + }
|
| + }
|
| + *frame_data++ = marker;
|
| + inputs[i].sz += index_sz + 1;
|
| }
|
| + } else {
|
| + // Found a super frame.
|
| + uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
|
| + uint8_t *frame_start = frame_data;
|
| + for (frame = 0; frame < frame_count; ++frame) {
|
| + // Looking for a visible frame.
|
| + if (frame_data[0] & 0x02) {
|
| + ++frames_found;
|
| + if (frames_found == remained_spatial_layers)
|
| + break;
|
| + }
|
| + frame_data += frame_sizes[frame];
|
| + }
|
| + ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. "
|
| + << "remained_spatial_layers: " << remained_spatial_layers
|
| + << " super_frame: " << i
|
| + << " is_multiple_frame_context: " << is_multiple_frame_contexts;
|
| + if (frame == frame_count - 1 && !is_multiple_frame_contexts)
|
| + continue;
|
| +
|
| frame_data += frame_sizes[frame];
|
| +
|
| + // We need to add one more frame for multiple frame contexts.
|
| + if (is_multiple_frame_contexts)
|
| + ++frame;
|
| + uint8_t marker =
|
| + static_cast<const uint8_t*>(inputs[i].buf)[inputs[i].sz - 1];
|
| + const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
| + const size_t index_sz = 2 + mag * frame_count;
|
| + const size_t new_index_sz = 2 + mag * (frame + 1);
|
| + marker &= 0x0f8;
|
| + marker |= frame;
|
| +
|
| + // Copy existing frame sizes.
|
| + memmove(frame_data + (is_multiple_frame_contexts ? 2 : 1),
|
| + frame_start + inputs[i].sz - index_sz + 1, new_index_sz - 2);
|
| + if (is_multiple_frame_contexts) {
|
| + // Add a one byte frame with flag show_existing_frame.
|
| + *frame_data++ = 0x88 | (remained_spatial_layers - 1);
|
| + }
|
| + // New marker.
|
| + frame_data[0] = marker;
|
| + frame_data += (mag * (frame + 1) + 1);
|
| +
|
| + if (is_multiple_frame_contexts) {
|
| + // Write the frame size for the one byte frame.
|
| + frame_data -= mag;
|
| + *frame_data++ = 1;
|
| + for (uint32_t j = 1; j < mag; ++j) {
|
| + *frame_data++ = 0;
|
| + }
|
| + }
|
| +
|
| + *frame_data++ = marker;
|
| + inputs[i].sz = frame_data - frame_start;
|
| +
|
| + if (is_multiple_frame_contexts) {
|
| + // Change the show frame flag to 0 for all frames.
|
| + for (int j = 0; j < frame; ++j) {
|
| + frame_start[0] &= ~2;
|
| + frame_start += frame_sizes[j];
|
| + }
|
| + }
|
| }
|
| - ASSERT_LT(frame, frame_count);
|
| - if (frame == frame_count - 1)
|
| - continue;
|
| -
|
| - frame_data += frame_sizes[frame];
|
| - uint8_t marker =
|
| - static_cast<const uint8_t *>(inputs[i].buf)[inputs[i].sz - 1];
|
| - const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
| - const size_t index_sz = 2 + mag * frame_count;
|
| - const size_t new_index_sz = 2 + mag * (frame + 1);
|
| - marker &= 0x0f8;
|
| - marker |= frame;
|
| - frame_data[0] = marker;
|
| - memcpy(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
|
| - new_index_sz - 2);
|
| - frame_data[new_index_sz - 1] = marker;
|
| - inputs[i].sz = frame_data - frame_start + new_index_sz;
|
| }
|
| }
|
|
|
| @@ -326,7 +405,7 @@
|
| }
|
|
|
| TEST_F(SvcTest, SetLayersOption) {
|
| - vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=3");
|
| + vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3");
|
| EXPECT_EQ(VPX_CODEC_OK, res);
|
| InitializeEncoder();
|
| EXPECT_EQ(3, svc_.spatial_layers);
|
| @@ -334,7 +413,7 @@
|
|
|
| TEST_F(SvcTest, SetMultipleOptions) {
|
| vpx_codec_err_t res =
|
| - vpx_svc_set_options(&svc_, "layers=2 scale-factors=1/3,2/3");
|
| + vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3");
|
| EXPECT_EQ(VPX_CODEC_OK, res);
|
| InitializeEncoder();
|
| EXPECT_EQ(2, svc_.spatial_layers);
|
| @@ -496,7 +575,7 @@
|
| FreeBitstreamBuffers(&outputs[0], 20);
|
| }
|
|
|
| -TEST_F(SvcTest, TwoPassEncode2LayersDecodeBaseLayerOnly) {
|
| +TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
|
| // First pass encode
|
| std::string stats_buf;
|
| Pass1EncodeNFrames(10, 2, &stats_buf);
|
| @@ -507,12 +586,12 @@
|
| vpx_fixed_buf outputs[10];
|
| memset(&outputs[0], 0, sizeof(outputs));
|
| Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
| - DropEnhancementLayers(&outputs[0], 10, 1);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, false);
|
| DecodeNFrames(&outputs[0], 10);
|
| FreeBitstreamBuffers(&outputs[0], 10);
|
| }
|
|
|
| -TEST_F(SvcTest, TwoPassEncode5LayersDecode54321Layers) {
|
| +TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
|
| // First pass encode
|
| std::string stats_buf;
|
| Pass1EncodeNFrames(10, 5, &stats_buf);
|
| @@ -525,13 +604,13 @@
|
| Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
|
|
|
| DecodeNFrames(&outputs[0], 10);
|
| - DropEnhancementLayers(&outputs[0], 10, 4);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 4, false);
|
| DecodeNFrames(&outputs[0], 10);
|
| - DropEnhancementLayers(&outputs[0], 10, 3);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 3, false);
|
| DecodeNFrames(&outputs[0], 10);
|
| - DropEnhancementLayers(&outputs[0], 10, 2);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, false);
|
| DecodeNFrames(&outputs[0], 10);
|
| - DropEnhancementLayers(&outputs[0], 10, 1);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, false);
|
| DecodeNFrames(&outputs[0], 10);
|
|
|
| FreeBitstreamBuffers(&outputs[0], 10);
|
| @@ -568,12 +647,212 @@
|
| memset(&outputs[0], 0, sizeof(outputs));
|
| Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
|
| DecodeNFrames(&outputs[0], 20);
|
| - DropEnhancementLayers(&outputs[0], 20, 2);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 20, 2, false);
|
| DecodeNFrames(&outputs[0], 20);
|
| - DropEnhancementLayers(&outputs[0], 20, 1);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 20, 1, false);
|
| DecodeNFrames(&outputs[0], 20);
|
|
|
| FreeBitstreamBuffers(&outputs[0], 20);
|
| }
|
|
|
| +TEST_F(SvcTest, SetMultipleFrameContextsOption) {
|
| + svc_.spatial_layers = 5;
|
| + vpx_codec_err_t res =
|
| + vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
|
| + EXPECT_EQ(VPX_CODEC_OK, res);
|
| + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
| + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
| +
|
| + svc_.spatial_layers = 2;
|
| + res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
|
| + InitializeEncoder();
|
| +}
|
| +
|
| +TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + Pass1EncodeNFrames(10, 2, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, true);
|
| + DecodeNFrames(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest,
|
| + TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + Pass1EncodeNFrames(10, 2, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
| + DecodeNFrames(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
|
| + Pass1EncodeNFrames(10, 2, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1 "
|
| + "multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, true);
|
| + DecodeNFrames(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest,
|
| + TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
|
| + Pass1EncodeNFrames(10, 3, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
|
| + "multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
|
| +
|
| + vpx_fixed_buf outputs_new[10];
|
| + for (int i = 0; i < 10; ++i) {
|
| + outputs_new[i].buf = malloc(outputs[i].sz + 16);
|
| + ASSERT_TRUE(outputs_new[i].buf != NULL);
|
| + memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
| + outputs_new[i].sz = outputs[i].sz;
|
| + }
|
| + DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 3, true);
|
| + DecodeNFrames(&outputs_new[0], 10);
|
| +
|
| + for (int i = 0; i < 10; ++i) {
|
| + memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
| + outputs_new[i].sz = outputs[i].sz;
|
| + }
|
| + DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 2, true);
|
| + DecodeNFrames(&outputs_new[0], 10);
|
| +
|
| + for (int i = 0; i < 10; ++i) {
|
| + memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
| + outputs_new[i].sz = outputs[i].sz;
|
| + }
|
| + DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 1, true);
|
| + DecodeNFrames(&outputs_new[0], 10);
|
| +
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs_new[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1");
|
| + svc_.temporal_layers = 2;
|
| + Pass1EncodeNFrames(10, 1, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + svc_.temporal_layers = 2;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
| + DecodeNFrames(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1");
|
| + svc_.temporal_layers = 2;
|
| + Pass1EncodeNFrames(10, 1, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + svc_.temporal_layers = 2;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
|
| + "multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
| + DecodeNFrames(&outputs[0], 10);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1");
|
| + svc_.temporal_layers = 2;
|
| + Pass1EncodeNFrames(10, 1, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + svc_.temporal_layers = 2;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
| +
|
| + vpx_fixed_buf base_layer[5];
|
| + for (int i = 0; i < 5; ++i)
|
| + base_layer[i] = outputs[i * 2];
|
| +
|
| + DecodeNFrames(&base_layer[0], 5);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| +TEST_F(SvcTest,
|
| + TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) {
|
| + // First pass encode
|
| + std::string stats_buf;
|
| + vpx_svc_set_options(&svc_, "scale-factors=1/1");
|
| + svc_.temporal_layers = 2;
|
| + Pass1EncodeNFrames(10, 1, &stats_buf);
|
| +
|
| + // Second pass encode
|
| + codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
| + svc_.temporal_layers = 2;
|
| + codec_enc_.g_error_resilient = 0;
|
| + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
|
| + "multi-frame-contexts=1");
|
| + vpx_fixed_buf outputs[10];
|
| + memset(&outputs[0], 0, sizeof(outputs));
|
| + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
| + DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
| +
|
| + vpx_fixed_buf base_layer[5];
|
| + for (int i = 0; i < 5; ++i)
|
| + base_layer[i] = outputs[i * 2];
|
| +
|
| + DecodeNFrames(&base_layer[0], 5);
|
| + FreeBitstreamBuffers(&outputs[0], 10);
|
| +}
|
| +
|
| } // namespace
|
|
|