blob: d603aaced6286e343aa3457d9444c695d76ac6f5 [file] [log] [blame]
// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// 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 STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_
#define STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_
#include <vector>
#include "starboard/common/log.h"
#include "starboard/common/ref_counted.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/types.h"
namespace starboard {
namespace shared {
namespace starboard {
namespace media {
// Parse avc nalus produced by the Cobalt demuxer.
// It makes the following assumptions:
// 1. It won't be used frequently. So it aimed to be easy to use, instead of
// being efficient.
// 2. The data it processes is produced by Cobalt, and should be valid most of
// of the time. The class won't crash on invalid input, but besides checking
// if the input starts with a nalu header, it doesn't do any further
// validations. It is up to the decoder to detect invalid input.
// 3. It assumes that multiple sps/pps nalus in different orders are different
// parameter sets.
class AvcParameterSets {
public:
enum Format {
kAnnexB,
kHeadless,
};
static const size_t kAnnexBHeaderSizeInBytes = 4;
static const uint8_t kSpsStartCode = 0x67;
static const uint8_t kPpsStartCode = 0x68;
// Only |format == kAnnexB| is supported, which is checked in the ctor.
AvcParameterSets(Format format, const uint8_t* data, size_t size);
Format format() const { return format_; }
bool is_valid() const { return is_valid_; }
bool has_sps_and_pps() const {
return first_sps_index_ != -1 && first_pps_index_ != -1;
}
const std::vector<uint8_t>& first_sps() const {
SB_DCHECK(first_sps_index_ != -1);
return parameter_sets_[first_sps_index_];
}
const std::vector<uint8_t>& first_pps() const {
SB_DCHECK(first_pps_index_ != -1);
return parameter_sets_[first_pps_index_];
}
std::vector<const uint8_t*> GetAddresses() const {
std::vector<const uint8_t*> addresses;
for (auto& parameter_set : parameter_sets_) {
addresses.push_back(parameter_set.data());
}
return addresses;
}
std::vector<size_t> GetSizesInBytes() const {
std::vector<size_t> sizes_in_bytes;
for (auto& parameter_set : parameter_sets_) {
sizes_in_bytes.push_back(parameter_set.size());
}
return sizes_in_bytes;
}
size_t combined_size_in_bytes() const { return combined_size_in_bytes_; }
AvcParameterSets ConvertTo(Format new_format) const;
bool operator==(const AvcParameterSets& that) const;
bool operator!=(const AvcParameterSets& that) const;
private:
Format format_ = kAnnexB;
bool is_valid_ = false;
int first_sps_index_ = -1;
int first_pps_index_ = -1;
std::vector<std::vector<uint8_t>> parameter_sets_;
size_t combined_size_in_bytes_ = 0;
};
// The function will fail only when the input doesn't start with an Annex B
// nalu header.
bool ConvertAnnexBToAvcc(const uint8_t* annex_b_source,
size_t size,
uint8_t* avcc_destination);
} // namespace media
} // namespace starboard
} // namespace shared
} // namespace starboard
#endif // STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_