Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/byte range streams #127

Merged
merged 48 commits into from
Nov 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
9e664f0
First checkin for the implementation of Byte Ranges in Readium SDK (W…
nleme Oct 21, 2014
e7b7d62
added missing Package API (so I can compile LauncherOSX and test the …
danielweck Oct 22, 2014
e2e2249
fixes memory leaks and crashes with FilterData()
danielweck Oct 23, 2014
94eaa5b
Obfuscated fonts: added missing support for application/font-XXX, whe…
danielweck Oct 23, 2014
1a43b1e
yet another AbsolutePath() BasePath() side-effect, see https://github…
danielweck Oct 23, 2014
56509a5
enabled supportsRange on font obfuscator, so we can test a real conte…
danielweck Oct 23, 2014
6a791df
Making sure that RDPackageResource is set to the proper offset when d…
nleme Oct 27, 2014
28396e4
Merge branch 'develop' into feature/ByteRangeStreams
nleme Oct 30, 2014
cbb6bba
Checking in the new PassThroughFilter class
nleme Oct 30, 2014
964ca86
Fixing a previous bad merge
nleme Oct 30, 2014
d899248
Changing the smart pointer for the vector of byte streams
nleme Oct 31, 2014
8a9bb20
Font (de)obfuscation does not support byte range (was set for testing…
danielweck Nov 5, 2014
2f8bcbb
addresses comments in https://github.com/readium/readium-sdk/commit/6…
danielweck Nov 5, 2014
97618ea
fallback to non-byte-range content stream in cases whereby a resource…
danielweck Nov 5, 2014
b611ac9
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 5, 2014
6abc02c
in the process of testing Media Overlays byte range content stream wi…
danielweck Nov 5, 2014
1b72667
added missing code to support byte ranges passing through a compatibl…
danielweck Nov 5, 2014
1d0369a
minor change in filter_chain (IsFullRange is satisfactory, no need to…
danielweck Nov 5, 2014
5738e4a
check for existence of RangeFilterContext on the client side of Filte…
danielweck Nov 5, 2014
c08d7c0
split filter_chain classes into separate files (no renaming yet)
danielweck Nov 6, 2014
e30e94a
wrapped "async" code within SUPPORT_ASYNC pre-processor conditional d…
danielweck Nov 6, 2014
5a03070
renamed ByteStream / ContentFilter classes and accessors (FilterChain…
danielweck Nov 6, 2014
18d500a
iOS launcher compile and run fine (in sync with OSX)
danielweck Nov 6, 2014
a1dd2b2
Various changes in Readium SDK (and some associated changes in RDServ…
nleme Nov 7, 2014
0834f92
Small correction on my previous checkin
nleme Nov 8, 2014
cb174c1
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 10, 2014
bc86c60
addresses #120 (URL percent decode / sanitize)
danielweck Nov 10, 2014
bea4cc2
disabled printf() message
danielweck Nov 10, 2014
1d6c357
iOS in sync with OSX launcher app (Readium SDK URL percent encode fix…
danielweck Nov 11, 2014
5f500af
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 11, 2014
5e08053
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 11, 2014
83efaea
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 11, 2014
85c3b1c
addresses #122 (some auto-generated EPUBs Quark / InDesign contain ne…
danielweck Nov 12, 2014
8f322bf
Merge branch 'develop' into feature/ByteRangeStreams
danielweck Nov 12, 2014
98218ed
script that encodes a file (e.g. audio / video) using a simple byte-p…
danielweck Nov 13, 2014
450caf2
ah syntax error
danielweck Nov 13, 2014
73ab9d3
tab / spaces normalisation
danielweck Nov 13, 2014
2363be1
temporarily polutting the PassThroughFilter with a real-fake de-encod…
danielweck Nov 14, 2014
cb8869b
Final chunk of refactoring for Byte Range streams
nleme Nov 14, 2014
94c4d59
remove unnecessary seek (costly IO) + disabled PassThrough filter for…
danielweck Nov 16, 2014
711e916
Changes based on Code Reviews
nleme Nov 17, 2014
686068f
Fixing an issue for extracting byte ranges when there is no ContentFi…
nleme Nov 17, 2014
7b5a7fa
ByteStream cached contentLength is updated when the "proper" ByteStre…
danielweck Nov 18, 2014
ded9965
fixed HTTP chunk bug (must be treated separately from HTTP byte range…
danielweck Nov 18, 2014
989518c
to avoid allocating/destroying temporary buffers when reading a filte…
danielweck Nov 18, 2014
75b53a6
4-spaces replaced with tab character
danielweck Nov 18, 2014
e5a5cf2
Clean up of latest development efforts
nleme Nov 19, 2014
2430e57
fixed typo in method name, removed Java and shell script for sample e…
danielweck Nov 20, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Platform/Apple/RDServices/Main/RDContainer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

@interface RDContainer () {
@private std::shared_ptr<ePub3::Container> m_container;
@private __weak id <RDContainerDelegate> m_delegate;
@private __weak id <RDContainerDelegate> m_delegate;
@private NSMutableArray *m_packages;
@private ePub3::Container::PackageList m_packageList;
@private NSString *m_path;
Expand All @@ -58,26 +58,26 @@ - (RDPackage *)firstPackage {


- (instancetype)initWithDelegate:(id <RDContainerDelegate>)delegate path:(NSString *)path {
if (path == nil || ![[NSFileManager defaultManager] fileExistsAtPath:path]) {
if (path == nil || ![[NSFileManager defaultManager] fileExistsAtPath:path]) {
return nil;
}

if (self = [super init]) {
m_delegate = delegate;
m_delegate = delegate;

ePub3::ErrorHandlerFn sdkErrorHandler = ^(const ePub3::error_details& err) {
ePub3::ErrorHandlerFn sdkErrorHandler = ^(const ePub3::error_details& err) {

const char * msg = err.message();
[m_delegate container:self handleSdkError:[NSString stringWithUTF8String:msg]];
const char * msg = err.message();
[m_delegate container:self handleSdkError:[NSString stringWithUTF8String:msg]];

//TODO? pass to delegate more information from ePub3::error_details (see error_handler.h)
//TODO? pass to delegate more information from ePub3::error_details (see error_handler.h)

return ePub3::DefaultErrorHandler(err);
};
ePub3::SetErrorHandler(sdkErrorHandler);
return ePub3::DefaultErrorHandler(err);
};
ePub3::SetErrorHandler(sdkErrorHandler);

ePub3::InitializeSdk();
ePub3::PopulateFilterManager();
ePub3::InitializeSdk();
ePub3::PopulateFilterManager();

m_path = path;
m_container = ePub3::Container::OpenContainer(path.UTF8String);
Expand Down
7 changes: 7 additions & 0 deletions Platform/Apple/RDServices/Main/RDPackage.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,11 @@
// Returns the resource at the given relative path or nil if it doesn't exist.
- (RDPackageResource *)resourceAtRelativePath:(NSString *)relativePath;

// Gets the current Byte Stream and returns the proper Byte Stream for the case.
// There can be three possible byte streams:
// - A simple ZipFileByteStream when no ContentFilter objects apply for this resource.
// - A FilterChainByteStreamRange when a Byte Range request has been made, and only one ContentFilter object applies.
// - A FilterChainByteStream when it is not a Byte Range request or more than one ContentFilter applies.
- (void *)getProperByteStream:(NSString *)relativePath currentByteStream:(void *)currentByteStream isRangeRequest:(BOOL)isRangeRequest;

@end
136 changes: 83 additions & 53 deletions Platform/Apple/RDServices/Main/RDPackage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
#import "RDSpineItem.h"


@interface RDPackage() <RDPackageResourceDelegate> {
@private std::vector<std::unique_ptr<ePub3::ByteStream>> m_byteStreamVector;
@interface RDPackage() {
@private RDMediaOverlaysSmilModel *m_mediaOverlaysSmilModel;
@private RDNavigationElement *m_navElemListOfFigures;
@private RDNavigationElement *m_navElemListOfIllustrations;
Expand Down Expand Up @@ -109,7 +108,7 @@ - (NSDictionary *)dictionary {
if (sss != nil) {
[dictRoot setObject:sss forKey:@"rendition_spread"];
}

NSString *ssss = self.renditionOrientation;
if (ssss != nil) {
[dictRoot setObject:ssss forKey:@"rendition_orientation"];
Expand Down Expand Up @@ -260,18 +259,6 @@ - (NSString *)packageID {
}


- (void)packageResourceWillDeallocate:(RDPackageResource *)packageResource {
for (auto i = m_byteStreamVector.begin(); i != m_byteStreamVector.end(); i++) {
if (i->get() == packageResource.byteStream) {
m_byteStreamVector.erase(i);
return;
}
}

NSLog(@"The byte stream was not found!");
}


- (RDNavigationElement *)pageList {
if (m_navElemPageList == nil) {
ePub3::NavigationTable *navTable = m_package->PageList().get();
Expand All @@ -284,75 +271,75 @@ - (RDNavigationElement *)pageList {
}

- (NSString *)findProperty:(NSString *)propName withOptionalPrefix:(NSString *)prefix {
NSString *value = [self findProperty:propName withPrefix:prefix];

if (value.length == 0) {
value = [self findProperty:propName withPrefix:@""];
}

return value;
NSString *value = [self findProperty:propName withPrefix:prefix];
if (value.length == 0) {
value = [self findProperty:propName withPrefix:@""];
}
return value;
}


- (NSString *)findProperty:(NSString *)propName withPrefix:(NSString *)prefix {
auto prop = m_package->PropertyMatching([propName UTF8String], [prefix UTF8String]);

if (prop != nullptr) {
return [NSString stringWithUTF8String:prop->Value().c_str()];
}

return @"";
auto prop = m_package->PropertyMatching([propName UTF8String], [prefix UTF8String]);
if (prop != nullptr) {
return [NSString stringWithUTF8String:prop->Value().c_str()];
}
return @"";
}

- (NSString *)renditionLayout {
return [self findProperty:@"layout" withPrefix:@"rendition"];
return [self findProperty:@"layout" withPrefix:@"rendition"];
}
- (NSString *)renditionFlow {
return [self findProperty:@"flow" withPrefix:@"rendition"];
return [self findProperty:@"flow" withPrefix:@"rendition"];
}
- (NSString *)renditionSpread {
return [self findProperty:@"spread" withPrefix:@"rendition"];
return [self findProperty:@"spread" withPrefix:@"rendition"];
}
- (NSString *)renditionOrientation {
return [self findProperty:@"orientation" withPrefix:@"rendition"];
return [self findProperty:@"orientation" withPrefix:@"rendition"];
}


- (RDPackageResource *)resourceAtRelativePath:(NSString *)relativePath {
if (relativePath == nil || relativePath.length == 0) {
return nil;
}

NSRange range = [relativePath rangeOfString:@"#"];

if (range.location != NSNotFound) {
relativePath = [relativePath substringToIndex:range.location];
}

ePub3::string s = ePub3::string(relativePath.UTF8String);
std::unique_ptr<ePub3::ByteStream> byteStream = m_package->ReadStreamForRelativePath(s);

if (byteStream == nullptr) {
NSLog(@"Relative path '%@' does not have a byte stream!", relativePath);
if (byteStream == nullptr)
{
NSLog(@"Relative path '%@' is not present in the book.", relativePath);
return nil;
}


ePub3::ConstManifestItemPtr manifestItem = m_package->ManifestItemAtRelativePath(s);
if (manifestItem == nullptr) {
NSLog(@"Relative path '%@' does not have a manifest item!", relativePath);
return nil;
}

RDPackageResource *resource = [[RDPackageResource alloc]
initWithDelegate:self
byteStream:byteStream.get()
package:self
relativePath:relativePath];

initWithByteStream:byteStream.release()
package:self
relativePath:relativePath];

if (resource != nil) {
m_byteStreamVector.push_back(std::move(byteStream));
ePub3::ConstManifestItemPtr item = m_package->ManifestItemAtRelativePath(s);

if (item) {
const ePub3::ManifestItem::MimeType &mediaType = item->MediaType();
resource.mimeType = [NSString stringWithUTF8String:mediaType.c_str()];
}
const ePub3::ManifestItem::MimeType &mediaType = manifestItem->MediaType();
resource.mimeType = [NSString stringWithUTF8String:mediaType.c_str()];
}

return resource;
}

Expand Down Expand Up @@ -397,4 +384,47 @@ - (NSString *)title {
}


- (void *)getProperByteStream:(NSString *)relativePath currentByteStream:(void *)currentByteStream isRangeRequest:(BOOL)isRangeRequest {
if (relativePath == nil || relativePath.length == 0) {
return nil;
}

NSRange range = [relativePath rangeOfString:@"#"];

if (range.location != NSNotFound) {
relativePath = [relativePath substringToIndex:range.location];
}
ePub3::string s = ePub3::string(relativePath.UTF8String);

ePub3::ConstManifestItemPtr manifestItem = m_package->ManifestItemAtRelativePath(s);
if (manifestItem == nullptr) {
NSLog(@"Relative path '%@' does not have a manifest item!", relativePath);
return nil;
}
ePub3::ManifestItemPtr m = std::const_pointer_cast<ePub3::ManifestItem>(manifestItem);

size_t numFilters = m_package->GetFilterChainSize(m);
ePub3::ByteStream *byteStream = nullptr;
ePub3::SeekableByteStream *rawInput = dynamic_cast<ePub3::SeekableByteStream *>((ePub3::ByteStream *)currentByteStream);

if (numFilters == 0)
{
byteStream = (ePub3::ByteStream *) currentByteStream; // is actually a SeekableByteStream
}
else if (numFilters == 1 && isRangeRequest)
{
byteStream = m_package->GetFilterChainByteStreamRange(m, rawInput).release(); // is *not* a SeekableByteStream, but wraps one
if (byteStream == nullptr)
{
byteStream = m_package->GetFilterChainByteStream(m, rawInput).release(); // is *not* a SeekableByteStream, but wraps one
}
}
else
{
byteStream = m_package->GetFilterChainByteStream(m, rawInput).release(); // is *not* a SeekableByteStream, but wraps one
}

return byteStream;
}

@end
14 changes: 3 additions & 11 deletions Platform/Apple/RDServices/Main/RDPackageResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,22 @@
@class RDPackage;
@class RDPackageResource;

@protocol RDPackageResourceDelegate <NSObject>

- (void)packageResourceWillDeallocate:(RDPackageResource *)packageResource;

@end

@interface RDPackageResource : NSObject

@property (nonatomic, readonly) void *byteStream;
@property (nonatomic, readonly) NSUInteger contentLength;
@property (nonatomic, readonly) NSData *data;
@property (nonatomic, copy) NSString *mimeType;
@property (nonatomic, readonly) RDPackage *package;

// The relative path associated with this resource.
@property (nonatomic, readonly) NSString *relativePath;

- (instancetype)
initWithDelegate:(id <RDPackageResourceDelegate>)delegate
byteStream:(void *)byteStream
initWithByteStream:(void *)byteStream
package:(RDPackage *)package
relativePath:(NSString *)relativePath;

- (NSData *)readDataOfLength:(NSUInteger)length;
- (void)setOffset:(UInt64)offset;
- (NSData *)readDataFull;
- (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeRequest:(BOOL)isRangeRequest;

@end
Loading