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:
KongQun Yang 2016-02-03 15:58:35 -08:00
parent bb3918e62b
commit 38c30bd7a1
4 changed files with 58 additions and 28 deletions

View File

@ -586,7 +586,7 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
count = audio_entries.size(); count = audio_entries.size();
break; break;
case kText: case kText:
count = wvtt_entries.size(); count = text_entries.size();
break; break;
default: default:
NOTIMPLEMENTED() << "SampleDecryption type " << type NOTIMPLEMENTED() << "SampleDecryption type " << type
@ -609,8 +609,8 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
RCHECK(reader->ReadAllChildren(&audio_entries)); RCHECK(reader->ReadAllChildren(&audio_entries));
RCHECK(audio_entries.size() == count); RCHECK(audio_entries.size() == count);
} else if (type == kText) { } else if (type == kText) {
RCHECK(reader->ReadAllChildren(&wvtt_entries)); RCHECK(reader->ReadAllChildren(&text_entries));
RCHECK(wvtt_entries.size() == count); RCHECK(text_entries.size() == count);
} }
} else { } else {
DCHECK_LT(0u, count); DCHECK_LT(0u, count);
@ -622,7 +622,7 @@ bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
RCHECK(buffer->ReadWriteChild(&audio_entries[i])); RCHECK(buffer->ReadWriteChild(&audio_entries[i]));
} else if (type == kText) { } else if (type == kText) {
for (uint32_t i = 0; i < count; ++i) for (uint32_t i = 0; i < count; ++i)
RCHECK(buffer->ReadWriteChild(&wvtt_entries[i])); RCHECK(buffer->ReadWriteChild(&text_entries[i]));
} else { } else {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
@ -638,6 +638,9 @@ uint32_t SampleDescription::ComputeSizeInternal() {
} else if (type == kAudio) { } else if (type == kAudio) {
for (uint32_t i = 0; i < audio_entries.size(); ++i) for (uint32_t i = 0; i < audio_entries.size(); ++i)
box_size += audio_entries[i].ComputeSize(); 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; return box_size;
} }
@ -1589,25 +1592,37 @@ uint32_t WebVTTSourceLabelBox::ComputeSizeInternal() {
return HeaderSize() + source_label.size(); return HeaderSize() + source_label.size();
} }
WVTTSampleEntry::WVTTSampleEntry() {} TextSampleEntry::TextSampleEntry() : format(FOURCC_NULL) {}
WVTTSampleEntry::~WVTTSampleEntry() {} TextSampleEntry::~TextSampleEntry() {}
FourCC WVTTSampleEntry::BoxType() const { FourCC TextSampleEntry::BoxType() const {
return FOURCC_wvtt; 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) {
// TODO(rkuroiwa): Handle the optional MPEG4BitRateBox. if (buffer->Reading()) {
RCHECK(ReadWriteHeaderInternal(buffer) && DCHECK(buffer->reader());
buffer->IgnoreBytes(6) && // reserved for SampleEntry. format = buffer->reader()->type();
buffer->ReadWriteUInt16(&data_reference_index) && } else {
buffer->PrepareChildren() && RCHECK(ReadWriteHeaderInternal(buffer));
buffer->ReadWriteChild(&config) && }
buffer->ReadWriteChild(&label)); RCHECK(buffer->IgnoreBytes(6) && // reserved for SampleEntry.
buffer->ReadWriteUInt16(&data_reference_index));
if (format == FOURCC_wvtt) {
// TODO(rkuroiwa): Handle the optional MPEG4BitRateBox.
RCHECK(buffer->PrepareChildren() &&
buffer->ReadWriteChild(&config) &&
buffer->ReadWriteChild(&label));
}
return true; return true;
} }
uint32_t WVTTSampleEntry::ComputeSizeInternal() { uint32_t TextSampleEntry::ComputeSizeInternal() {
// 6 for the (anonymous) reserved bytes for SampleEntry class. // 6 for the (anonymous) reserved bytes for SampleEntry class.
return HeaderSize() + 6 + sizeof(data_reference_index) + return HeaderSize() + 6 + sizeof(data_reference_index) +
config.ComputeSize() + label.ComputeSize(); config.ComputeSize() + label.ComputeSize();
@ -1762,7 +1777,7 @@ bool MediaInformation::ReadWriteInternal(BoxBuffer* buffer) {
RCHECK(buffer->ReadWriteChild(&smhd)); RCHECK(buffer->ReadWriteChild(&smhd));
break; break;
case kText: case kText:
RCHECK(buffer->ReadWriteChild(&sthd)); RCHECK(buffer->TryReadWriteChild(&sthd));
break; break;
default: default:
NOTIMPLEMENTED(); NOTIMPLEMENTED();

View File

@ -374,11 +374,16 @@ struct WebVTTSourceLabelBox : Box {
std::string source_label; std::string source_label;
}; };
struct WVTTSampleEntry : Box { struct TextSampleEntry : Box {
DECLARE_BOX_METHODS(WVTTSampleEntry); 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; uint16_t data_reference_index;
// Sub boxes for wvtt text sample entry.
WebVTTConfigurationBox config; WebVTTConfigurationBox config;
WebVTTSourceLabelBox label; WebVTTSourceLabelBox label;
// Optional MPEG4BitRateBox. // Optional MPEG4BitRateBox.
@ -392,7 +397,7 @@ struct SampleDescription : FullBox {
// SampleEntry struct, std::vector<SampleEntry> sample_entries. // SampleEntry struct, std::vector<SampleEntry> sample_entries.
std::vector<VideoSampleEntry> video_entries; std::vector<VideoSampleEntry> video_entries;
std::vector<AudioSampleEntry> audio_entries; std::vector<AudioSampleEntry> audio_entries;
std::vector<WVTTSampleEntry> wvtt_entries; std::vector<TextSampleEntry> text_entries;
}; };
struct DecodingTime { struct DecodingTime {

View File

@ -270,8 +270,7 @@ inline bool operator==(const WebVTTSourceLabelBox& lhs,
return lhs.source_label == rhs.source_label; return lhs.source_label == rhs.source_label;
} }
inline bool operator==(const WVTTSampleEntry& lhs, inline bool operator==(const TextSampleEntry& lhs, const TextSampleEntry& rhs) {
const WVTTSampleEntry& rhs) {
return lhs.config == rhs.config && lhs.label == rhs.label; return lhs.config == rhs.config && lhs.label == rhs.label;
} }

View File

@ -54,7 +54,7 @@ class BoxDefinitionsTestGeneral : public testing::Test {
return true; 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) { bool ReadBack(VideoSampleEntry* video) {
scoped_ptr<BoxReader> reader(CreateReader()); scoped_ptr<BoxReader> reader(CreateReader());
std::vector<VideoSampleEntry> video_entries; std::vector<VideoSampleEntry> video_entries;
@ -64,7 +64,7 @@ class BoxDefinitionsTestGeneral : public testing::Test {
return true; 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) { bool ReadBack(AudioSampleEntry* audio) {
scoped_ptr<BoxReader> reader(CreateReader()); scoped_ptr<BoxReader> reader(CreateReader());
std::vector<AudioSampleEntry> audio_entries; std::vector<AudioSampleEntry> audio_entries;
@ -74,6 +74,16 @@ class BoxDefinitionsTestGeneral : public testing::Test {
return true; 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 // SampleDescription cannot parse on its own. Its type parameter should
// be preset before scanning the box. // be preset before scanning the box.
bool ReadBack(SampleDescription* stsd) { bool ReadBack(SampleDescription* stsd) {
@ -429,12 +439,13 @@ class BoxDefinitionsTestGeneral : public testing::Test {
vlab->source_label = "another_label"; vlab->source_label = "another_label";
} }
void Fill(WVTTSampleEntry* wvtt) { void Fill(TextSampleEntry* wvtt) {
wvtt->format = FOURCC_wvtt;
Fill(&wvtt->config); Fill(&wvtt->config);
Fill(&wvtt->label); Fill(&wvtt->label);
} }
void Modify(WVTTSampleEntry* wvtt) { void Modify(TextSampleEntry* wvtt) {
Modify(&wvtt->config); Modify(&wvtt->config);
Modify(&wvtt->label); Modify(&wvtt->label);
} }
@ -953,7 +964,7 @@ typedef testing::Types<FileType,
AudioSampleEntry, AudioSampleEntry,
WebVTTConfigurationBox, WebVTTConfigurationBox,
WebVTTSourceLabelBox, WebVTTSourceLabelBox,
WVTTSampleEntry, TextSampleEntry,
SampleDescription, SampleDescription,
DecodingTimeToSample, DecodingTimeToSample,
CompositionTimeToSample, CompositionTimeToSample,