blob: 712bc82806127b3775000964941790cdb9896300 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 2008 PacketVideo
*
* 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 "access_unit_impl.h"
#include "oscl_string_utils.h"
/* **********************************************
*
* NOTE: Throughout this implementation, fragment number 0
* is reserved for the Codec Info.
*
* **********************************************/
OSCL_EXPORT_REF
AccessUnitImplementation::AccessUnitImplementation(const int num_reserved_frags)
{
// the default constructor for BufFragGroup takes care of other things
timestamp = 0;
length = 0;
num_fragments = num_reserved_fragments = num_reserved_frags;
// reserve fragment 0 for CodecInfo
fragments[0].ptr = NULL;
fragments[0].len = 0;
buffer_states[0] = NULL;
}
AccessUnitImplementation::~AccessUnitImplementation()
{
// decrement the ref count on all buffers
for (uint ii = 0; ii < num_fragments; ++ii)
{
if (buffer_states[ii])
{
buffer_states[ii]->decrement_refcnt();
}
}
}
MediaStatusClass::status_t AccessUnitImplementation::AddCodecInfo(BufferFragment& fragment)
{
if (fragments[0].ptr != NULL)
{
// already codec info
return MediaStatusClass::FIXED_FRAG_LOC_FULL;
}
return AddLocalFragment(fragment, (int32) 0);
}
MediaStatusClass::status_t AccessUnitImplementation::AddCodecInfo(void *ptr, int len)
{
if (fragments[0].ptr != NULL)
{
// already codec info
return MediaStatusClass::FIXED_FRAG_LOC_FULL;
}
BufferFragment fragment;
fragment.ptr = ptr;
fragment.len = len;
return AddLocalFragment(fragment, (int32) 0);
}
MediaStatusClass::status_t AccessUnitImplementation::AddAUFrag(const BufferFragment& frag, BufferState* buffer_state,
int32 location_offset)
{
location_offset = (location_offset >= 0) ? location_offset + 1 : location_offset;
return AddFragment(frag, buffer_state, location_offset);
}
MediaStatusClass::status_t AccessUnitImplementation::AddLocalAUFrag(const BufferFragment& frag, int32 location_offset)
{
location_offset = (location_offset >= 0) ? location_offset + 1 : location_offset;
return AddLocalFragment(frag, location_offset);
}
void AccessUnitImplementation::GetMediaFragment(uint32 index, BufferFragment& frag, BufferState*& buffer_state) const
{
if (index + num_reserved_fragments >= num_fragments)
{
buffer_state = NULL;
frag.ptr = NULL;
frag.len = 0;
return;
}
frag.ptr = fragments[index + num_reserved_fragments].ptr;
frag.len = fragments[index + num_reserved_fragments].len;
buffer_state = buffer_states[index + num_reserved_fragments];
}
// bit_pattern_masks assume MSB first
const uint8 bit_pattern_masks[7] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xE0, 0xC0, 0x80 };
//
// the follow routine seeks forward or backward, depending on delta_in_bytes
// It returns true if successfully seeked to the desired place or reached MediaData boundary; the
// latter case the flag boundaryReached is set to ture, and ptr to the last byte if it is the
// end boundary reached, or points to first byte if the begin of the AccessUnit is reached..
// Otherwise it returns false when errors such as state corruption are detected.
//
bool AccessUnitImplementation::seek(int & idx, int & offset, uint8 * & ptr, bool & boundaryReached,
const int delta_in_bytes)
{
int32 first_frag_size = this->fragments[idx+num_reserved_fragments].len - offset;
boundaryReached = false;
BufferFragment * frag;
if (first_frag_size < 0)
{
// state inconsistency
return false;
}
if (delta_in_bytes > 0) // seek forward
{
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
if (first_frag_size >= delta_in_bytes)
{
offset += delta_in_bytes;
ptr = (uint8 *) frag->ptr + offset;
// ptr = (this->GetMediaFragment(idx))->ptr + offset + delta_in_bytes;
return true;
}
int32 remain = delta_in_bytes - first_frag_size;
idx++;
while (idx < (int) this->GetNumMediaFrags())
{
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
if ((int32) frag->len >= remain) // found
{
offset = remain;
ptr = (uint8 *) frag->ptr + remain;
return true;
}
else
{
remain -= frag->len;
idx++;
}
}
// reached end of MediaData
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
offset = frag->len;
ptr = (uint8 *) frag->ptr + offset - 1;
boundaryReached = true;
return true;
}
else // delta is negative, seek backwards
{
if (offset >= oscl_abs(delta_in_bytes))
{
offset += delta_in_bytes;
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
ptr = (uint8 *) frag->ptr + offset; // should use GetMediaFragment
return true;
}
else
{
boundaryReached = true;
return true;
}
int32 remain = delta_in_bytes + offset;
while (idx >= 0)
{
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
if ((int32) frag->len > oscl_abs(remain))
{
offset = frag->len + remain;
ptr = (uint8 *) frag->ptr + remain;
return true;
}
else
{
remain += frag->len;
}
idx--;
}
// We are back to the begining of the MediaData. Return (0, 0)
idx = offset = 0;
frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
ptr = (uint8 *) frag->ptr;
boundaryReached = true;
return true;
}
}
// returns true if matched or error happened (such as bound reached unexpectedly);
// else return false;
bool AccessUnitImplementation::match_bit_pattern_no_state(const int idx, const int offset, const uint8 * pattern,
const uint8 pattern_size_in_bits)
{
uint8 num_bytes = pattern_size_in_bits / 8;
uint8 bits_in_fraction = pattern_size_in_bits % 8;
uint8 bit_mask = 0xff; // start with full mask
if (bits_in_fraction > 0)
{
// build the bit mask for the fractional byte
bit_mask = bit_pattern_masks[7 - bits_in_fraction];
/*
uint8 tmp = 1;
for (uint8 ii=0; ii<(8-bits_in_fraction); ii++) {
bit_mask -= tmp;
tmp *= 2;
}
*/
}
BufferFragment * frag = GetMediaFragment(idx);
if (NULL == frag)
return false;
octet * tmp_ptr = (uint8 *) frag->ptr + offset;
// Either num_bytes = 0 or no match;
// Now we need to figure out next state
bool boundaryReached;
/* the following does not work due to endianess
uint32 tmp_marker = *(uint32 *) tmp_ptr;
if (tmp_marker == 0x00008000 & 0xffff8000) {
// printf("Resysnch marker found at idx = %d, offset = %d\n", idx, offset);
// exit(1);
return true;
}
*/
int tmp_idx = idx;
int tmp_offset = offset;
for (uint8 ii = 0; ii < num_bytes; ii++)
{
if ((* tmp_ptr) != pattern[ii])
{
return false;
}
else
{
this->seek(tmp_idx, tmp_offset, tmp_ptr, boundaryReached, 1);
if (boundaryReached)
{
return true;
}
}
}
// printf("The whole %d octets are matched, now matching %d bits in the fraction byte\n", num_bytes, bits_in_fraction);
if (bits_in_fraction)
{
if (((*tmp_ptr) & bit_mask) == (pattern[num_bytes] & bit_mask))
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
} // end of method
// state indicates the num of bytes to move back to.
int32 AccessUnitImplementation::match_bit_pattern_with_state(const int32 idx, const int32 offset, const uint8 * pattern,
const uint8 pattern_size_in_bits, const int32 state)
{
uint8 num_bytes = pattern_size_in_bits / 8;
uint8 bits_in_fraction = pattern_size_in_bits % 8;
uint8 bit_mask = 0xff; // start with full mask
if (bits_in_fraction > 0)
{
// build the bit mask for the fractional byte
bit_mask = bit_pattern_masks[7 - bits_in_fraction];
/*
uint8 tmp = 1;
for (uint8 ii=0; ii<(8-bits_in_fraction); ii++) {
bit_mask -= tmp;
tmp *= 2;
}
*/
}
BufferFragment * frag = GetMediaFragment(idx);
if (NULL == frag)
{
// printf("Error in pattern_match_with_state\n");
return 0;
}
if (offset >= (int) frag->len)
{
return 1;
}
octet * tmp_ptr = (uint8 *) frag->ptr + offset;
// uint8 num_bytes_to_match = state;
uint8 num_bits_to_match;
if (state*8 > pattern_size_in_bits)
{
num_bits_to_match = pattern_size_in_bits;
}
else
{
num_bits_to_match = state * 8;
}
if ((num_bytes > 0) && this->match_bit_pattern_no_state(idx, offset, pattern, num_bits_to_match))
{
return 0; // 0 means matched;
}
else
{
// Either num_bytes = 0 or no match;
// Now we need to figure out next state
for (uint8 ii = 1; ii < num_bytes; ii++)
{
if (this->match_bit_pattern_no_state(idx, offset, (pattern + ii), pattern_size_in_bits - ii*8))
{
return ii;
}
}
if (bits_in_fraction && ((*tmp_ptr & bit_mask) == (pattern[num_bytes] & bit_mask)))
{
return num_bytes;
}
else
{
return (num_bytes + 1);
}
}
} // end of method