From 1354a1ddc55f0f87194c10ce161528d4d9698f07 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 16 Feb 2010 18:11:57 +0530
Subject: [PATCH] serve frames and videos with X-Sendfile header
---
README | 4 ++++
apache/vhost.conf.in | 17 +++++++++++------
pandora/backend/models.py | 10 +++++++++-
pandora/backend/urls.py | 2 ++
pandora/backend/views.py | 24 +++++++++++++++++++++++-
pandora/settings.py | 2 ++
6 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/README b/README
index 810806f..7598514 100644
--- a/README
+++ b/README
@@ -30,3 +30,7 @@ Development:
we are using django, http://docs.djangoproject.com/en/dev/
communication between webserver and background tasks is done via rabbitmq
http://github.com/ask/carrot/ for more info on the lib used to communicate
+
+
+Apache setup:
+ sudo apt-get install libapache2-mod-wsgi libapache2-mod-xsendfile
diff --git a/apache/vhost.conf.in b/apache/vhost.conf.in
index cbcfb11..8811d4b 100644
--- a/apache/vhost.conf.in
+++ b/apache/vhost.conf.in
@@ -8,16 +8,21 @@
Allow from all
- Alias /.bzr /oxdb/.bzr
- Alias /static __PREFIX__/oxdb/static
- Alias /favicon.ico __PREFIX__/oxdb/static/favicon.ico
- Alias /media __PREFIX__/oxdb/media
+
+ XSendFile on
+ XSendFileAllowAbove on
+
+
+ Alias /.bzr __PREFIX__/.bzr
+ Alias /static __PREFIX__/pandora/static
+ Alias /favicon.ico __PREFIX__/pandora/static/favicon.ico
+ Alias /media __PREFIX__/pandora/media
Alias /admin/media __PREFIX__/src/django/django/contrib/admin/media
Alias /static/js/jquery.js __PREFIX__/src/django/django/contrib/admin/media/js/jquery.min.js
WSGIScriptAlias / __PREFIX__/wsgi/django.wsgi
- WSGIDaemonProcess oxdb user=oxdb group=oxdb threads=25 python-path=__PREFIX__/lib/python2.6/site-packages/
- WSGIProcessGroup oxdb
+ WSGIDaemonProcess pandora user=pandora group=pandora threads=25 python-path=__PREFIX__/lib/python2.6/site-packages/
+ WSGIProcessGroup pandora
ServerSignature Off
diff --git a/pandora/backend/models.py b/pandora/backend/models.py
index b36b6cd..e7f610a 100644
--- a/pandora/backend/models.py
+++ b/pandora/backend/models.py
@@ -10,6 +10,7 @@ from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
+from django.conf import settings
from oxdjango import fields
import oxlib
@@ -430,6 +431,11 @@ class Movie(models.Model):
self.get('series_title', ''), self.get('episode_title', ''),
self.get('season', ''), self.get('episode', ''))
+ def frame(self, position, width=128):
+ #FIXME: compute offset and so on
+ f = self.files.all()[0]
+ return f.frame(position, width)
+
def updateFind(self):
try:
f = self.find
@@ -1155,7 +1161,9 @@ class File(models.Model):
def frame(self, position, width=128):
videoFile = getattr(self, 'stream_%s'%settings.VIDEO_PROFILE).path
frameFolder = os.path.join(os.path.dirname(videoFile), 'frames')
- extract.frame(videoFile, position, frameFolder, width)
+ if position<= self.duration:
+ return extract.frame(videoFile, position, frameFolder, width)
+ return None
def editable(self, user):
'''
diff --git a/pandora/backend/urls.py b/pandora/backend/urls.py
index 4810956..b1a9ffe 100644
--- a/pandora/backend/urls.py
+++ b/pandora/backend/urls.py
@@ -6,6 +6,8 @@ from django.conf.urls.defaults import *
urlpatterns = patterns("backend.views",
(r'^upload/$', 'firefogg_upload'),
+ (r'^frame/(?P.*)/(?P.*)\.(?P\d+).jpg$', 'frame'),
+ (r'^stream/(?P.*).(?P.*).ogv$', 'video'),
(r'^$', 'api'),
)
diff --git a/pandora/backend/views.py b/pandora/backend/views.py
index 8e30cff..f23dd1a 100644
--- a/pandora/backend/views.py
+++ b/pandora/backend/views.py
@@ -1,17 +1,19 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
+from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import json
+import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count
-from django.http import HttpResponse
+from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
from django.template import RequestContext
from django.conf import settings
@@ -23,6 +25,8 @@ except ImportError:
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
+from oxdjango.http import HttpFileResponse
+import oxlib
import models
import utils
@@ -630,6 +634,24 @@ def api_subtitles(request):
l = models.Subtitles.objects.filter(movie_file__oshash=oshash).values('language')
response['data']['languages'] = [f['language'] for f in l]
return render_to_json_response(response)
+
+def video(request, id, quality):
+ movie = get_object_or_404(models.Movie, movieId=id)
+ if quality not in settings.VIDEO_ENCODING:
+ raise Http404
+ stream = getattr(movie, 'stream_'+quality)
+ response = HttpFileResponse(stream.path, content_type='video/ogg')
+ #FIXME: movie needs duration field
+ #response['Content-Duration'] = movie.duration
+ return response
+
+def frame(request, id, position, size):
+ movie = get_object_or_404(models.Movie, movieId=id)
+ position = oxlib.time2ms(position)/1000
+ frame = movie.frame(position, int(size))
+ if not frame:
+ raise Http404
+ return HttpFileResponse(frame, content_type='image/jpeg')
'''
GET list
diff --git a/pandora/settings.py b/pandora/settings.py
index 8c7ea24..0b35d6c 100644
--- a/pandora/settings.py
+++ b/pandora/settings.py
@@ -13,6 +13,8 @@ DEBUG = True
TEMPLATE_DEBUG = DEBUG
JSON_DEBUG = False
+XSENDFILE = False
+
ADMINS = (
('j', 'j@mailb.org'),
)