Allow other text sample entries than wvtt
Before this change, the media file will fail to be parsed if it contains non-wvtt text streams. This change allows demuxing of video and audio streams in these media files even though the text stream is ignored. Fixes #74. Change-Id: I7ef108a51125c4965fe48c39efe9638f3a0e4759
This commit is contained in:
parent
bb3918e62b
commit
38c30bd7a1
|
@ -586,7 +586,7 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
count = audio_entries.size();
|
||||
break;
|
||||
case kText:
|
||||
count = wvtt_entries.size();
|
||||
count = text_entries.size();
|
||||
break;
|
||||
default:
|
||||
NOTIMPLEMENTED() << "SampleDecryption type " << type
|
||||
|
@ -609,8 +609,8 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
RCHECK(reader->ReadAllChildren(&audio_entries));
|
||||
RCHECK(audio_entries.size() == count);
|
||||
} else if (type == kText) {
|
||||
RCHECK(reader->ReadAllChildren(&wvtt_entries));
|
||||
RCHECK(wvtt_entries.size() == count);
|
||||
RCHECK(reader->ReadAllChildren(&text_entries));
|
||||
RCHECK(text_entries.size() == count);
|
||||
}
|
||||
} else {
|
||||
DCHECK_LT(0u, count);
|
||||
|
@ -622,7 +622,7 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
RCHECK(buffer->ReadWriteChild(&audio_entries[i]));
|
||||
} else if (type == kText) {
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
RCHECK(buffer->ReadWriteChild(&wvtt_entries[i]));
|
||||
RCHECK(buffer->ReadWriteChild(&text_entries[i]));
|
||||
} else {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
@ -638,6 +638,9 @@ uint32_t SampleDescription::ComputeSizeInternal() {
|
|||
} else if (type == kAudio) {
|
||||
for (uint32_t i = 0; i < audio_entries.size(); ++i)
|
||||
box_size += audio_entries[i].ComputeSize();
|
||||
} else if (type == kText) {
|
||||
for (uint32_t i = 0; i < text_entries.size(); ++i)
|
||||
box_size += text_entries[i].ComputeSize();
|
||||
}
|
||||
return box_size;
|
||||
}
|
||||
|
@ -1589,25 +1592,37 @@ uint32_t WebVTTSourceLabelBox::ComputeSizeInternal() {
|
|||
return HeaderSize() + source_label.size();
|
||||
}
|
||||
|
||||
WVTTSampleEntry::WVTTSampleEntry() {}
|
||||
WVTTSampleEntry::~WVTTSampleEntry() {}
|
||||
TextSampleEntry::TextSampleEntry() : format(FOURCC_NULL) {}
|
||||
TextSampleEntry::~TextSampleEntry() {}
|
||||
|
||||
FourCC WVTTSampleEntry::BoxType() const {
|
||||
return FOURCC_wvtt;
|
||||
FourCC TextSampleEntry::BoxType() const {
|
||||
if (format == FOURCC_NULL) {
|
||||
LOG(ERROR) << "TextSampleEntry should be parsed according to the "
|
||||
<< "handler type recovered in its Media ancestor.";
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
bool WVTTSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
|
||||
bool TextSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
|
||||
if (buffer->Reading()) {
|
||||
DCHECK(buffer->reader());
|
||||
format = buffer->reader()->type();
|
||||
} else {
|
||||
RCHECK(ReadWriteHeaderInternal(buffer));
|
||||
}
|
||||
RCHECK(buffer->IgnoreBytes(6) && // reserved for SampleEntry.
|
||||
buffer->ReadWriteUInt16(&data_reference_index));
|
||||
|
||||
if (format == FOURCC_wvtt) {
|
||||
// TODO(rkuroiwa): Handle the optional MPEG4BitRateBox.
|
||||
RCHECK(ReadWriteHeaderInternal(buffer) &&
|
||||
buffer->IgnoreBytes(6) && // reserved for SampleEntry.
|
||||
buffer->ReadWriteUInt16(&data_reference_index) &&
|
||||
buffer->PrepareChildren() &&
|
||||
RCHECK(buffer->PrepareChildren() &&
|
||||
buffer->ReadWriteChild(&config) &&
|
||||
buffer->ReadWriteChild(&label));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t WVTTSampleEntry::ComputeSizeInternal() {
|
||||
uint32_t TextSampleEntry::ComputeSizeInternal() {
|
||||
// 6 for the (anonymous) reserved bytes for SampleEntry class.
|
||||
return HeaderSize() + 6 + sizeof(data_reference_index) +
|
||||
config.ComputeSize() + label.ComputeSize();
|
||||
|
@ -1762,7 +1777,7 @@ bool MediaInformation::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
RCHECK(buffer->ReadWriteChild(&smhd));
|
||||
break;
|
||||
case kText:
|
||||
RCHECK(buffer->ReadWriteChild(&sthd));
|
||||
RCHECK(buffer->TryReadWriteChild(&sthd));
|
||||
break;
|
||||
default:
|
||||
NOTIMPLEMENTED();
|
||||
|
|
|
@ -374,11 +374,16 @@ struct WebVTTSourceLabelBox : Box {
|
|||
std::string source_label;
|
||||
};
|
||||
|
||||
struct WVTTSampleEntry : Box {
|
||||
DECLARE_BOX_METHODS(WVTTSampleEntry);
|
||||
struct TextSampleEntry : Box {
|
||||
DECLARE_BOX_METHODS(TextSampleEntry);
|
||||
|
||||
// Specifies fourcc of this sample entry. It needs to be set on write, e.g.
|
||||
// set to 'wvtt' to write WVTTSampleEntry; On read, it is recovered from box
|
||||
// header.
|
||||
FourCC format;
|
||||
uint16_t data_reference_index;
|
||||
|
||||
// Sub boxes for wvtt text sample entry.
|
||||
WebVTTConfigurationBox config;
|
||||
WebVTTSourceLabelBox label;
|
||||
// Optional MPEG4BitRateBox.
|
||||
|
@ -392,7 +397,7 @@ struct SampleDescription : FullBox {
|
|||
// SampleEntry struct, std::vector<SampleEntry> sample_entries.
|
||||
std::vector<VideoSampleEntry> video_entries;
|
||||
std::vector<AudioSampleEntry> audio_entries;
|
||||
std::vector<WVTTSampleEntry> wvtt_entries;
|
||||
std::vector<TextSampleEntry> text_entries;
|
||||
};
|
||||
|
||||
struct DecodingTime {
|
||||
|
|
|
@ -270,8 +270,7 @@ inline bool operator==(const WebVTTSourceLabelBox& lhs,
|
|||
return lhs.source_label == rhs.source_label;
|
||||
}
|
||||
|
||||
inline bool operator==(const WVTTSampleEntry& lhs,
|
||||
const WVTTSampleEntry& rhs) {
|
||||
inline bool operator==(const TextSampleEntry& lhs, const TextSampleEntry& rhs) {
|
||||
return lhs.config == rhs.config && lhs.label == rhs.label;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class BoxDefinitionsTestGeneral : public testing::Test {
|
|||
return true;
|
||||
}
|
||||
|
||||
// FourCC for VideoSampleEntry is not a constant, e.g. could be avc1, or encv.
|
||||
// FourCC for VideoSampleEntry is fixed, e.g. could be avc1, or encv.
|
||||
bool ReadBack(VideoSampleEntry* video) {
|
||||
scoped_ptr<BoxReader> reader(CreateReader());
|
||||
std::vector<VideoSampleEntry> video_entries;
|
||||
|
@ -64,7 +64,7 @@ class BoxDefinitionsTestGeneral : public testing::Test {
|
|||
return true;
|
||||
}
|
||||
|
||||
// FourCC for AudioSampleEntry is not a constant, e.g. could be mp4a, or enca.
|
||||
// FourCC for AudioSampleEntry is fixed, e.g. could be mp4a, or enca.
|
||||
bool ReadBack(AudioSampleEntry* audio) {
|
||||
scoped_ptr<BoxReader> reader(CreateReader());
|
||||
std::vector<AudioSampleEntry> audio_entries;
|
||||
|
@ -74,6 +74,16 @@ class BoxDefinitionsTestGeneral : public testing::Test {
|
|||
return true;
|
||||
}
|
||||
|
||||
// FourCC for TextSampleEntry is fixed, e.g. could be text, or wvtt.
|
||||
bool ReadBack(TextSampleEntry* text) {
|
||||
scoped_ptr<BoxReader> reader(CreateReader());
|
||||
std::vector<TextSampleEntry> text_entries;
|
||||
RCHECK(reader->ReadAllChildren(&text_entries));
|
||||
RCHECK(text_entries.size() == 1);
|
||||
*text = text_entries[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
// SampleDescription cannot parse on its own. Its type parameter should
|
||||
// be preset before scanning the box.
|
||||
bool ReadBack(SampleDescription* stsd) {
|
||||
|
@ -429,12 +439,13 @@ class BoxDefinitionsTestGeneral : public testing::Test {
|
|||
vlab->source_label = "another_label";
|
||||
}
|
||||
|
||||
void Fill(WVTTSampleEntry* wvtt) {
|
||||
void Fill(TextSampleEntry* wvtt) {
|
||||
wvtt->format = FOURCC_wvtt;
|
||||
Fill(&wvtt->config);
|
||||
Fill(&wvtt->label);
|
||||
}
|
||||
|
||||
void Modify(WVTTSampleEntry* wvtt) {
|
||||
void Modify(TextSampleEntry* wvtt) {
|
||||
Modify(&wvtt->config);
|
||||
Modify(&wvtt->label);
|
||||
}
|
||||
|
@ -953,7 +964,7 @@ typedef testing::Types<FileType,
|
|||
AudioSampleEntry,
|
||||
WebVTTConfigurationBox,
|
||||
WebVTTSourceLabelBox,
|
||||
WVTTSampleEntry,
|
||||
TextSampleEntry,
|
||||
SampleDescription,
|
||||
DecodingTimeToSample,
|
||||
CompositionTimeToSample,
|
||||
|
|
Loading…
Reference in New Issue