* Use chunked encoding on resized images, so we can send out the header before transcoding.

This commit is contained in:
Justin Maggard 2009-11-10 20:09:04 +00:00
parent db4b8d0a02
commit 71e399b4a6

View File

@ -1361,28 +1361,28 @@ void
SendResp_resizedimg(struct upnphttp * h, char * object) SendResp_resizedimg(struct upnphttp * h, char * object)
{ {
char header[1500]; char header[1500];
char sql_buf[256]; char str_buf[256];
char **result; char **result;
char date[30]; char date[30];
char dlna_pn[4]; char dlna_pn[4];
time_t curtime = time(NULL); time_t curtime = time(NULL);
int width=640, height=480, dstw, dsth, rotation, size; int width=640, height=480, dstw, dsth, rotation, size;
unsigned char * data; long srcw, srch;
unsigned char * data = NULL;
char *path, *file_path; char *path, *file_path;
char *resolution, *tn; char *resolution, *tn;
char *key, *val; char *key, *val;
char *saveptr=NULL, *item=NULL; char *saveptr=NULL, *item=NULL;
char *pixelshape=NULL; char *pixelshape=NULL;
sqlite_int64 id; sqlite_int64 id;
int rows=0, ret; int rows=0, chunked=0, ret;
ExifData *ed; ExifData *ed;
ExifLoader *l; ExifLoader *l;
image * imsrc; image *imsrc = NULL, *imdst = NULL;
image * imdst;
id = strtoll(object, NULL, 10); id = strtoll(object, NULL, 10);
sprintf(sql_buf, "SELECT PATH, RESOLUTION, THUMBNAIL from DETAILS where ID = '%lld'", id); sprintf(str_buf, "SELECT PATH, RESOLUTION, THUMBNAIL from DETAILS where ID = '%lld'", id);
ret = sql_get_table(db, sql_buf, &result, &rows, NULL); ret = sql_get_table(db, str_buf, &result, &rows, NULL);
if( (ret != SQLITE_OK) ) if( (ret != SQLITE_OK) )
{ {
DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id); DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id);
@ -1405,6 +1405,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
file_path = result[3]; file_path = result[3];
resolution = result[4]; resolution = result[4];
tn = result[5]; tn = result[5];
srcw = strtol(resolution, &saveptr, 10);
srch = strtol(saveptr+1, NULL, 10);
path = strdup(object); path = strdup(object);
if( strtok_r(path, "?", &saveptr) ) if( strtok_r(path, "?", &saveptr) )
@ -1448,11 +1450,45 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
DPRINTF(E_INFO, L_HTTP, "Serving resized image for ObjectId: %lld [%s]\n", id, file_path); DPRINTF(E_INFO, L_HTTP, "Serving resized image for ObjectId: %lld [%s]\n", id, file_path);
/* Figure out the best destination resolution we can use */
dstw = width;
dsth = ((((width<<10)/srcw)*srch)>>10);
if( dsth > height )
{
dsth = height;
dstw = (((height<<10)/srch) * srcw>>10);
}
if( dstw <= 640 && dsth <= 480 )
strcpy(dlna_pn, "SM");
else if( dstw <= 1024 && dsth <= 768 )
strcpy(dlna_pn, "MED");
else
strcpy(dlna_pn, "LRG");
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
snprintf(header, sizeof(header)-100, "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_%s;DLNA.ORG_CI=1\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n",
date, dlna_pn);
if( h->reqflags & FLAG_XFERINTERACTIVE )
{
strcat(header, "transferMode.dlna.org: Interactive\r\n");
}
else if( h->reqflags & FLAG_XFERBACKGROUND )
{
strcat(header, "transferMode.dlna.org: Background\r\n");
}
/* Resizing from a thumbnail is much faster than from a large image */ /* Resizing from a thumbnail is much faster than from a large image */
#ifdef __sparc__ #ifdef __sparc__
if( width <= 200 && height <= 150 && atoi(tn) ) if( dstw <= 200 && dsth <= 150 && atoi(tn) )
#else #else
if( width <= 160 && height <= 120 && atoi(tn) ) if( dstw <= 160 && dsth <= 120 && atoi(tn) )
#endif #endif
{ {
l = exif_loader_new(); l = exif_loader_new();
@ -1470,62 +1506,58 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size); imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size);
exif_data_unref(ed); exif_data_unref(ed);
} }
else else if( strcmp(h->HttpVer, "HTTP/1.0") == 0 )
{ {
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0); imsrc = image_new_from_jpeg(file_path, 1, NULL, 0);
} }
if( !imsrc )
{
Send404(h);
goto resized_error;
}
/* Figure out the best destination resolution we can use */
dstw = width;
dsth = ((((width<<10)/imsrc->width)*imsrc->height)>>10);
if( dsth > height )
{
dsth = height;
dstw = (((height<<10)/imsrc->height) * imsrc->width>>10);
}
imdst = image_resize(imsrc, dstw, dsth);
data = image_save_to_jpeg_buf(imdst, &size);
if( dstw <= 640 && dsth <= 480 )
strcpy(dlna_pn, "SM");
else if( dstw <= 1024 && dsth <= 768 )
strcpy(dlna_pn, "MED");
else else
strcpy(dlna_pn, "LRG");
//DPRINTF(E_INFO, L_HTTP, "size: %d\n", size);
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
snprintf(header, sizeof(header)-50, "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %d\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_%s;DLNA.ORG_CI=1\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n",
size, date, dlna_pn);
if( h->reqflags & FLAG_XFERINTERACTIVE )
{ {
strcat(header, "transferMode.dlna.org: Interactive\r\n"); chunked = 1;
strcat(header, "Transfer-Encoding: chunked\r\n\r\n");
} }
else if( h->reqflags & FLAG_XFERBACKGROUND )
if( !chunked )
{ {
strcat(header, "transferMode.dlna.org: Background\r\n"); if( !imsrc )
{
Send404(h);
goto resized_error;
}
imdst = image_resize(imsrc, dstw, dsth);
data = image_save_to_jpeg_buf(imdst, &size);
sprintf(str_buf, "Content-Length: %d\r\n\r\n", size);
strcat(header, str_buf);
} }
strcat(header, "\r\n");
if( (send_data(h, header, strlen(header)) == 0) && (h->req_command != EHead) ) if( (send_data(h, header, strlen(header)) == 0) && (h->req_command != EHead) )
{ {
send_data(h, (char *)data, size); if( chunked )
{
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0);
if( !imsrc )
{
Send404(h);
goto resized_error;
}
imdst = image_resize(imsrc, dstw, dsth);
data = image_save_to_jpeg_buf(imdst, &size);
ret = sprintf(str_buf, "%x\r\n", size);
send_data(h, str_buf, ret);
send_data(h, (char *)data, size);
send_data(h, "\r\n0\r\n\r\n", 7);
}
else
{
send_data(h, (char *)data, size);
}
} }
DPRINTF(E_INFO, L_HTTP, "Done serving %s\n", file_path); DPRINTF(E_INFO, L_HTTP, "Done serving %s\n", file_path);
if( imdst )
image_free(imdst);
image_free(imsrc); image_free(imsrc);
image_free(imdst);
resized_error: resized_error:
sqlite3_free_table(result); sqlite3_free_table(result);
#if USE_FORK #if USE_FORK