am f0ad5484: Merge "In the absence of width/height information in the sdp, extract the dimensions from the avc codec specific data." into gingerbread

Merge commit 'f0ad54846168f07fc1fd7f18cde93deea1559f86' into gingerbread-plus-aosp

* commit 'f0ad54846168f07fc1fd7f18cde93deea1559f86':
  In the absence of width/height information in the sdp, extract the dimensions from the avc codec specific data.
This commit is contained in:
Andreas Huber
2010-08-19 10:56:40 -07:00
committed by Android Git Automerger
9 changed files with 160 additions and 70 deletions

View File

@@ -39,6 +39,7 @@ LOCAL_SRC_FILES:= \
TimedEventQueue.cpp \
Utils.cpp \
WAVExtractor.cpp \
avc_utils.cpp \
string.cpp
LOCAL_C_INCLUDES:= \

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "include/avc_utils.h"
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ADebug.h>
namespace android {
static unsigned parseUE(ABitReader *br) {
unsigned numZeroes = 0;
while (br->getBits(1) == 0) {
++numZeroes;
}
unsigned x = br->getBits(numZeroes);
return x + (1u << numZeroes) - 1;
}
// Determine video dimensions from the sequence parameterset.
void FindAVCDimensions(
const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height) {
ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1);
unsigned profile_idc = br.getBits(8);
br.skipBits(16);
parseUE(&br); // seq_parameter_set_id
if (profile_idc == 100 || profile_idc == 110
|| profile_idc == 122 || profile_idc == 244
|| profile_idc == 44 || profile_idc == 83 || profile_idc == 86) {
unsigned chroma_format_idc = parseUE(&br);
if (chroma_format_idc == 3) {
br.skipBits(1); // residual_colour_transform_flag
}
parseUE(&br); // bit_depth_luma_minus8
parseUE(&br); // bit_depth_chroma_minus8
br.skipBits(1); // qpprime_y_zero_transform_bypass_flag
CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag
}
parseUE(&br); // log2_max_frame_num_minus4
unsigned pic_order_cnt_type = parseUE(&br);
if (pic_order_cnt_type == 0) {
parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4
} else if (pic_order_cnt_type == 1) {
// offset_for_non_ref_pic, offset_for_top_to_bottom_field and
// offset_for_ref_frame are technically se(v), but since we are
// just skipping over them the midpoint does not matter.
br.getBits(1); // delta_pic_order_always_zero_flag
parseUE(&br); // offset_for_non_ref_pic
parseUE(&br); // offset_for_top_to_bottom_field
unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br);
for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
parseUE(&br); // offset_for_ref_frame
}
}
parseUE(&br); // num_ref_frames
br.getBits(1); // gaps_in_frame_num_value_allowed_flag
unsigned pic_width_in_mbs_minus1 = parseUE(&br);
unsigned pic_height_in_map_units_minus1 = parseUE(&br);
unsigned frame_mbs_only_flag = br.getBits(1);
*width = pic_width_in_mbs_minus1 * 16 + 16;
*height = (2 - frame_mbs_only_flag)
* (pic_height_in_map_units_minus1 * 16 + 16);
}
} // namespace android

View File

@@ -3,6 +3,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
AAtomizer.cpp \
ABitReader.cpp \
ABuffer.cpp \
ADebug.cpp \
AHandler.cpp \

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef AVC_UTILS_H_
#define AVC_UTILS_H_
#include <media/stagefright/foundation/ABuffer.h>
namespace android {
void FindAVCDimensions(
const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height);
} // namespace android
#endif // AVC_UTILS_H_

View File

@@ -16,9 +16,10 @@
#include "ATSParser.h"
#include "ABitReader.h"
#include "AnotherPacketSource.h"
#include "include/avc_utils.h"
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -473,60 +474,6 @@ static sp<ABuffer> FindNAL(
}
}
static unsigned parseUE(ABitReader *br) {
unsigned numZeroes = 0;
while (br->getBits(1) == 0) {
++numZeroes;
}
unsigned x = br->getBits(numZeroes);
return x + (1u << numZeroes) - 1;
}
// Determine video dimensions from the sequence parameterset.
static void FindDimensions(
const sp<ABuffer> seqParamSet, int32_t *width, int32_t *height) {
ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1);
unsigned profile_idc = br.getBits(8);
br.skipBits(16);
parseUE(&br); // seq_parameter_set_id
if (profile_idc == 100 || profile_idc == 110
|| profile_idc == 122 || profile_idc == 144) {
TRESPASS();
}
parseUE(&br); // log2_max_frame_num_minus4
unsigned pic_order_cnt_type = parseUE(&br);
if (pic_order_cnt_type == 0) {
parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4
} else if (pic_order_cnt_type == 1) {
br.getBits(1); // delta_pic_order_always_zero_flag
parseUE(&br); // offset_for_non_ref_pic
parseUE(&br); // offset_for_top_to_bottom_field
unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br);
for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
parseUE(&br); // offset_for_ref_frame
}
}
parseUE(&br); // num_ref_frames
br.getBits(1); // gaps_in_frame_num_value_allowed_flag
unsigned pic_width_in_mbs_minus1 = parseUE(&br);
unsigned pic_height_in_map_units_minus1 = parseUE(&br);
unsigned frame_mbs_only_flag = br.getBits(1);
*width = pic_width_in_mbs_minus1 * 16 + 16;
*height = (2 - frame_mbs_only_flag)
* (pic_height_in_map_units_minus1 * 16 + 16);
}
static sp<ABuffer> MakeAVCCodecSpecificData(
const sp<ABuffer> &buffer, int32_t *width, int32_t *height) {
const uint8_t *data = buffer->data();
@@ -537,7 +484,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData(
return NULL;
}
FindDimensions(seqParamSet, width, height);
FindAVCDimensions(seqParamSet, width, height);
size_t stopOffset;
sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);

View File

@@ -3,7 +3,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
ABitReader.cpp \
AnotherPacketSource.cpp \
ATSParser.cpp \
MPEG2TSExtractor.cpp \

View File

@@ -18,6 +18,8 @@
#include "ASessionDescription.h"
#include "avc_utils.h"
#include <ctype.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -96,7 +98,11 @@ static sp<ABuffer> decodeHex(const AString &s) {
return buffer;
}
static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) {
static sp<ABuffer> MakeAVCCodecSpecificData(
const char *params, int32_t *width, int32_t *height) {
*width = 0;
*height = 0;
AString val;
if (!GetAttribute(params, "profile-level-id", &val)) {
return NULL;
@@ -178,6 +184,11 @@ static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) {
memcpy(out, nal->data(), nal->size());
out += nal->size();
if (i == 0) {
FindAVCDimensions(nal, width, height);
LOG(INFO) << "dimensions " << *width << "x" << *height;
}
}
*out++ = numPicParameterSets;
@@ -193,7 +204,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) {
out += nal->size();
}
hexdump(csd->data(), csd->size());
// hexdump(csd->data(), csd->size());
return csd;
}
@@ -230,7 +241,7 @@ sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
hexdump(csd->data(), csd->size());
// hexdump(csd->data(), csd->size());
return csd;
}
@@ -260,22 +271,32 @@ APacketSource::APacketSource(
int32_t width, height;
if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
// TODO: extract dimensions from sequence parameter set.
width = -1;
height = -1;
}
int32_t encWidth, encHeight;
sp<ABuffer> codecSpecificData =
MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
if (codecSpecificData != NULL) {
if (width < 0) {
// If no explicit width/height given in the sdp, use the dimensions
// extracted from the first sequence parameter set.
width = encWidth;
height = encHeight;
}
mFormat->setData(
kKeyAVCC, 0,
codecSpecificData->data(), codecSpecificData->size());
} else if (width < 0) {
mInitCheck = ERROR_UNSUPPORTED;
return;
}
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
sp<ABuffer> codecSpecificData =
MakeAVCCodecSpecificData(params.c_str());
if (codecSpecificData != NULL) {
mFormat->setData(
kKeyAVCC, 0,
codecSpecificData->data(), codecSpecificData->size());
}
} else if (!strncmp(desc.c_str(), "H263-2000/", 10)
|| !strncmp(desc.c_str(), "H263-1998/", 10)) {
mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);