mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1196353 - Use standard Xiph extradata format to pass headers from demuxers to decoders. r=jya
This commit is contained in:
parent
b30cf3972d
commit
94ebb79c9f
80
dom/media/XiphExtradata.cpp
Normal file
80
dom/media/XiphExtradata.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "XiphExtradata.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool XiphHeadersToExtradata(MediaByteBuffer* aCodecSpecificConfig,
|
||||
const nsTArray<const unsigned char*>& aHeaders,
|
||||
const nsTArray<size_t>& aHeaderLens)
|
||||
{
|
||||
size_t nheaders = aHeaders.Length();
|
||||
if (!nheaders || nheaders > 255) return false;
|
||||
aCodecSpecificConfig->AppendElement(nheaders - 1);
|
||||
for (size_t i = 0; i < nheaders - 1; i++) {
|
||||
size_t headerLen;
|
||||
for (headerLen = aHeaderLens[i]; headerLen >= 255; headerLen -= 255) {
|
||||
aCodecSpecificConfig->AppendElement(255);
|
||||
}
|
||||
aCodecSpecificConfig->AppendElement(headerLen);
|
||||
}
|
||||
for (size_t i = 0; i < nheaders; i++) {
|
||||
aCodecSpecificConfig->AppendElements(aHeaders[i], aHeaderLens[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XiphExtradataToHeaders(nsTArray<unsigned char*>& aHeaders,
|
||||
nsTArray<size_t>& aHeaderLens,
|
||||
unsigned char* aData,
|
||||
size_t aAvailable)
|
||||
{
|
||||
size_t total = 0;
|
||||
if (aAvailable < 1) {
|
||||
return false;
|
||||
}
|
||||
aAvailable--;
|
||||
int nHeaders = *aData++ + 1;
|
||||
for (int i = 0; i < nHeaders - 1; i++) {
|
||||
size_t headerLen = 0;
|
||||
for (;;) {
|
||||
// After this test, we know that (aAvailable - total > headerLen) and
|
||||
// (headerLen >= 0) so (aAvailable - total > 0). The loop decrements
|
||||
// aAvailable by 1 and total remains fixed, so we know that in the next
|
||||
// iteration (aAvailable - total >= 0). Thus (aAvailable - total) can
|
||||
// never underflow.
|
||||
if (aAvailable - total <= headerLen) {
|
||||
return false;
|
||||
}
|
||||
// Since we know (aAvailable > total + headerLen), this can't overflow
|
||||
// unless total is near 0 and both aAvailable and headerLen are within
|
||||
// 255 bytes of the maximum representable size. However, that is
|
||||
// impossible, since we would have had to have gone through this loop
|
||||
// more than 255 times to make headerLen that large, and thus decremented
|
||||
// aAvailable more than 255 times.
|
||||
headerLen += *aData;
|
||||
aAvailable--;
|
||||
if (*aData++ != 255) break;
|
||||
}
|
||||
// And this check ensures updating total won't cause (aAvailable - total)
|
||||
// to underflow.
|
||||
if (aAvailable - total < headerLen) {
|
||||
return false;
|
||||
}
|
||||
aHeaderLens.AppendElement(headerLen);
|
||||
// Since we know aAvailable >= total + headerLen, this can't overflow.
|
||||
total += headerLen;
|
||||
}
|
||||
aHeaderLens.AppendElement(aAvailable);
|
||||
for (int i = 0; i < nHeaders; i++) {
|
||||
aHeaders.AppendElement(aData);
|
||||
aData += aHeaderLens[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
28
dom/media/XiphExtradata.h
Normal file
28
dom/media/XiphExtradata.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#if !defined(XiphExtradata_h)
|
||||
#define XiphExtradata_h
|
||||
|
||||
#include "MediaData.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/* This converts a list of headers to the canonical form of extradata for Xiph
|
||||
codecs in non-Ogg containers. We use it to pass those headers from demuxer
|
||||
to decoder even when demuxing from an Ogg cotainer. */
|
||||
bool XiphHeadersToExtradata(MediaByteBuffer* aCodecSpecificConfig,
|
||||
const nsTArray<const unsigned char*>& aHeaders,
|
||||
const nsTArray<size_t>& aHeaderLens);
|
||||
|
||||
/* This converts a set of extradata back into a list of headers. */
|
||||
bool XiphExtradataToHeaders(nsTArray<unsigned char*>& aHeaders,
|
||||
nsTArray<size_t>& aHeaderLens,
|
||||
unsigned char* aData,
|
||||
size_t aAvailable);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // XiphExtradata_h
|
@ -149,6 +149,7 @@ EXPORTS += [
|
||||
'VideoSegment.h',
|
||||
'VideoUtils.h',
|
||||
'VorbisUtils.h',
|
||||
'XiphExtradata.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
@ -245,6 +246,7 @@ UNIFIED_SOURCES += [
|
||||
'VideoTrackList.cpp',
|
||||
'VideoUtils.cpp',
|
||||
'WebVTTListener.cpp',
|
||||
'XiphExtradata.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "VorbisDecoder.h"
|
||||
#include "VorbisUtils.h"
|
||||
#include "XiphExtradata.h"
|
||||
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "nsAutoPtr.h"
|
||||
@ -71,23 +72,17 @@ VorbisDataDecoder::Init()
|
||||
PodZero(&mVorbisDsp);
|
||||
PodZero(&mVorbisBlock);
|
||||
|
||||
size_t available = mInfo.mCodecSpecificConfig->Length();
|
||||
uint8_t *p = mInfo.mCodecSpecificConfig->Elements();
|
||||
for(int i = 0; i < 3; i++) {
|
||||
if (available < 2) {
|
||||
nsAutoTArray<unsigned char*,4> headers;
|
||||
nsAutoTArray<size_t,4> headerLens;
|
||||
if (!XiphExtradataToHeaders(headers, headerLens,
|
||||
mInfo.mCodecSpecificConfig->Elements(),
|
||||
mInfo.mCodecSpecificConfig->Length())) {
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
for (size_t i = 0; i < headers.Length(); i++) {
|
||||
if (NS_FAILED(DecodeHeader(headers[i], headerLens[i]))) {
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
available -= 2;
|
||||
size_t length = BigEndian::readUint16(p);
|
||||
p += 2;
|
||||
if (available < length) {
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
available -= length;
|
||||
if (NS_FAILED(DecodeHeader((const unsigned char*)p, length))) {
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
p += length;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPacketCount == 3);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "MediaDataDemuxer.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "NesteggPacketHolder.h"
|
||||
#include "XiphExtradata.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
@ -378,6 +379,8 @@ WebMDemuxer::ReadMetadata()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoTArray<const unsigned char*,4> headers;
|
||||
nsAutoTArray<size_t,4> headerLens;
|
||||
for (uint32_t header = 0; header < nheaders; ++header) {
|
||||
unsigned char* data = 0;
|
||||
size_t length = 0;
|
||||
@ -385,13 +388,24 @@ WebMDemuxer::ReadMetadata()
|
||||
if (r == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Vorbis has 3 headers write length + data for each header
|
||||
if (nheaders > 1) {
|
||||
uint8_t c[2];
|
||||
BigEndian::writeUint16(&c[0], length);
|
||||
mInfo.mAudio.mCodecSpecificConfig->AppendElements(&c[0], 2);
|
||||
headers.AppendElement(data);
|
||||
headerLens.AppendElement(length);
|
||||
}
|
||||
|
||||
// Vorbis has 3 headers, convert to Xiph extradata format to send them to
|
||||
// the demuxer.
|
||||
// TODO: This is already the format WebM stores them in. Would be nice
|
||||
// to avoid having libnestegg split them only for us to pack them again,
|
||||
// but libnestegg does not give us an API to access this data directly.
|
||||
if (nheaders > 1) {
|
||||
if (!XiphHeadersToExtradata(mInfo.mAudio.mCodecSpecificConfig,
|
||||
headers, headerLens)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mInfo.mAudio.mCodecSpecificConfig->AppendElements(data, length);
|
||||
}
|
||||
else {
|
||||
mInfo.mAudio.mCodecSpecificConfig->AppendElements(headers[0],
|
||||
headerLens[0]);
|
||||
}
|
||||
uint64_t duration = 0;
|
||||
r = nestegg_duration(mContext, &duration);
|
||||
|
Loading…
Reference in New Issue
Block a user