Make the afc src loads faster by only connecting once, and by caching reads from the device for when gstreamer does loads of tiny reads close to each other.

This commit is contained in:
David Sansome 2010-08-04 20:33:48 +00:00
parent 0b85797e45
commit e3c8b00dfa
2 changed files with 52 additions and 22 deletions

View File

@ -135,18 +135,37 @@ static void gst_afc_src_init(GstAfcSrc* element, GstAfcSrcClass* gclass) {
element->location_ = NULL;
element->uuid_ = NULL;
element->path_ = NULL;
element->connected_ = false;
element->afc_ = NULL;
element->afc_port_ = 0;
element->device_ = NULL;
element->file_handle_ = 0;
element->lockdown_ = NULL;
element->buffer_ = NULL;
element->buffer_is_valid_ = false;
element->buffer_length_ = 0;
element->buffer_offset_ = 0;
}
static void gst_afc_src_finalize(GObject* object) {
GstAfcSrc* src = GST_AFCSRC(object);
free(src->location_);
free(src->uuid_);
free(src->path_);
GstAfcSrc* self = GST_AFCSRC(object);
free(self->location_);
free(self->uuid_);
free(self->path_);
free(self->buffer_);
if (self->file_handle_)
afc_file_close(self->afc_, self->file_handle_);
if (self->afc_)
afc_client_free(self->afc_);
if (self->lockdown_)
lockdownd_client_free(self->lockdown_);
if (self->device_)
idevice_free(self->device_);
G_OBJECT_CLASS(parent_class)->finalize(object);
}
@ -184,6 +203,10 @@ static void gst_afc_src_get_property(
static gboolean gst_afc_src_start(GstBaseSrc* src) {
GstAfcSrc* self = GST_AFCSRC(src);
// Don't connect again
if (self->connected_)
return true;
// Check that a URI has been passed
if (!self->location_ || self->location_[0] == '\0') {
GST_ELEMENT_ERROR(src, RESOURCE, NOT_FOUND, ("No URI specified"), (NULL));
@ -235,25 +258,12 @@ static gboolean gst_afc_src_start(GstBaseSrc* src) {
return false;
}
self->connected_ = true;
return true;
}
static gboolean gst_afc_src_stop(GstBaseSrc* src) {
GstAfcSrc* self = GST_AFCSRC(src);
if (self->file_handle_) {
afc_file_close(self->afc_, self->file_handle_);
}
if (self->afc_) {
afc_client_free(self->afc_);
}
if (self->lockdown_) {
lockdownd_client_free(self->lockdown_);
}
if (self->device_) {
idevice_free(self->device_);
}
return true;
}
@ -267,11 +277,25 @@ static GstFlowReturn gst_afc_src_create(GstBaseSrc* src, guint64 offset, guint l
return GST_FLOW_ERROR;
}
uint32_t bytes_read = 0;
if (length > 0) {
afc_file_seek(self->afc_, self->file_handle_, offset, SEEK_SET);
afc_file_read(self->afc_, self->file_handle_, (char*)(GST_BUFFER_DATA(buf)), length, &bytes_read);
// Is this section within our cache?
if (!self->buffer_is_valid_ || offset < self->buffer_offset_ ||
offset + length > self->buffer_offset_ + self->buffer_length_) {
// No - read from the device to fill our internal cache.
// Always read twice the requested size so the next read(s) hit the cache too.
if (self->buffer_length_ != length * 2) {
self->buffer_ = (char*)realloc(self->buffer_, length * 2);
self->buffer_is_valid_ = true;
self->buffer_length_ = length * 2;
}
self->buffer_offset_ = offset;
uint32_t bytes_read = 0;
afc_file_seek(self->afc_, self->file_handle_, offset, SEEK_SET);
afc_file_read(self->afc_, self->file_handle_, self->buffer_, length * 2, &bytes_read);
}
// Copy from our internal buffer to the output buffer
memcpy(GST_BUFFER_DATA(buf), self->buffer_ + offset - self->buffer_offset_, length);
*buffer = buf;
return GST_FLOW_OK;

View File

@ -49,6 +49,7 @@ struct _GstAfcSrc {
char* uuid_;
char* path_;
bool connected_;
idevice_t device_;
lockdownd_client_t lockdown_;
afc_client_t afc_;
@ -56,6 +57,11 @@ struct _GstAfcSrc {
uint16_t afc_port_;
uint64_t file_handle_;
bool buffer_is_valid_;
guint64 buffer_offset_;
guint buffer_length_;
char* buffer_;
};
struct _GstAfcSrcClass {