From bd6acc3548ce4666792ec956fdaea3fb59c51f00 Mon Sep 17 00:00:00 2001 From: Equip de Desenvolupadors de PBE Date: Fri, 14 Dec 2012 02:54:15 +0000 Subject: [PATCH] WIP con streaming... aun no va --- res/layout/main_activity.xml | 6 ++---- res/values/strings.xml | 1 + src/com/upc/pbe/upcnews/Directoris.java | 9 +-------- src/com/upc/pbe/upcnews/HLS.java | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------- src/com/upc/pbe/upcnews/MainActivity.java | 8 ++++---- src/com/upc/pbe/upcnews/ParentList.java | 12 +----------- src/com/upc/pbe/upcnews/VideoActivity.java | 39 ++++++++++++++++++--------------------- 7 files changed, 236 insertions(+), 100 deletions(-) diff --git a/res/layout/main_activity.xml b/res/layout/main_activity.xml index 0e13cd6..6f24bf7 100644 --- a/res/layout/main_activity.xml +++ b/res/layout/main_activity.xml @@ -11,16 +11,14 @@ Alerta! Llibreries de Vitamio no instal·lades! Alerta! Item type + Buffering... \ No newline at end of file diff --git a/src/com/upc/pbe/upcnews/Directoris.java b/src/com/upc/pbe/upcnews/Directoris.java index 301c3dc..5cc7f2f 100644 --- a/src/com/upc/pbe/upcnews/Directoris.java +++ b/src/com/upc/pbe/upcnews/Directoris.java @@ -6,8 +6,6 @@ import java.util.ArrayList; import java.util.concurrent.ExecutionException; import android.app.Activity; -import android.app.DownloadManager; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -61,12 +59,10 @@ public class Directoris extends Activity implements OnItemClickListener } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) @@ -106,8 +102,7 @@ public class Directoris extends Activity implements OnItemClickListener ArrayList m3u8parsed = p.parseFile(playlist); Log.d(TAG, "Parsing completat"); //Creem un gestor HLS - DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); - HLS h = new HLS(m3u8parsed,((UpcApp)getApplication()).getLocalPath(), manager); + HLS h = new HLS(m3u8parsed,((UpcApp)getApplication()).getLocalPath()); ((UpcApp)getApplication()).setHLS(h); //Iniciem la reproduccio Intent mIntent = new Intent(this, VideoActivity.class); @@ -142,12 +137,10 @@ public class Directoris extends Activity implements OnItemClickListener } catch (InterruptedException e1) { - // TODO Auto-generated catch block e1.printStackTrace(); } catch (ExecutionException e1) { - // TODO Auto-generated catch block e1.printStackTrace(); } } diff --git a/src/com/upc/pbe/upcnews/HLS.java b/src/com/upc/pbe/upcnews/HLS.java index 8c30f23..f914220 100644 --- a/src/com/upc/pbe/upcnews/HLS.java +++ b/src/com/upc/pbe/upcnews/HLS.java @@ -1,20 +1,27 @@ package com.upc.pbe.upcnews; +import io.vov.vitamio.widget.VideoView; + +import java.io.BufferedInputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; -import android.app.DownloadManager; -import android.app.DownloadManager.Request; +import android.app.AlertDialog; import android.content.Context; import android.net.TrafficStats; -import android.net.Uri; +import android.os.AsyncTask; import android.util.Log; +import android.view.LayoutInflater; +import android.widget.Toast; //Gestor del protocol HTTP Live Streaming public class HLS { - + private static long TRIGGER_PLAY; private static final String TAG = "HLS"; private ArrayList videos; private ArrayList segments; @@ -24,11 +31,15 @@ public class HLS private int currentSegment; private boolean endReached; private String localFolder; - private DownloadManager dm; private BandwidthMeasurer bm; + private boolean started; + private boolean ended; + private long totalDownloaded; + private VideoView video; + private VideoActivity vActivity; - public HLS(ArrayList parsed, String localFolder, DownloadManager manager) + public HLS(ArrayList parsed, String localFolder) { // Neteja el directori i inicialitza les variables File dir = new File(localFolder); @@ -45,8 +56,47 @@ public class HLS endReached = false; this.localFolder = localFolder; bm = new BandwidthMeasurer(); + started = ended = false; + totalDownloaded = 0; } + public void setBufferSize() + { + /* + * Supondremos todos los segmentos de misma duración + */ + if(qualities.get(currentQuality).getQuality() == -1) + { + /* + * No nos dicen la calidad, la pondremos al conocer la longitud del primer segmento + */ + TRIGGER_PLAY = -1; + } + else + { + //15 segundos de cancha para empezar + TRIGGER_PLAY = (long) (15 * qualities.get(currentQuality).getQuality()/8e3); + } + + } + + public void quitPlayer(VideoActivity v) + { + video.stopPlayback(); + v.finish(); + return; + } + + public void setVideoViewer(VideoView v) + { + video = v; + } + + public void setVideoActivity(VideoActivity v) + { + vActivity = v; + } + public void loadVideo() { // Carrega la qualitat i, a partir d'aixo, el seguent segment @@ -56,6 +106,7 @@ public class HLS { endReached = true; } + setBufferSize(); } public String next() throws IOException @@ -71,59 +122,47 @@ public class HLS } Segment seg = segments.get(currentSegment++); String path = localFolder+seg.getURL().substring(seg.getURL().lastIndexOf("/") + 1, seg.getURL().length()); - if(!new File(path).exists()) //Para qué bajarlo dos veces? + Log.d(TAG, seg.getName() + " " + seg.getURL()); + return path; + } + + public void updateQuality(long bps) + { + if ((bps <= qualities.get(currentQuality).getQuality()) && (bps != -1)) { - Log.d(TAG, seg.getName() + " " + seg.getURL()); - long startTime = System.currentTimeMillis(); - long segmentBytes = TrafficStats.getTotalRxBytes(); - descarregarguardar(seg.getURL(), localFolder); - double bps = bm.Measure(segmentBytes, startTime); - Log.d(TAG, "Velocitat actual (KB/s): " + (bps / 8e3)); - if ((bps <= qualities.get(currentQuality).getQuality()) && (bps != -1)) + int newQuality; + for(newQuality = 0; newQuality < qualities.size(); newQuality++) { - int newQuality; - for(newQuality = 0; newQuality < qualities.size(); newQuality++) - { - if(bps >= qualities.get(newQuality).getQuality()) - { - break; - } - } - if(currentQuality != newQuality) + if(bps >= qualities.get(newQuality).getQuality()) { - currentQuality = newQuality; - currentVideo--; //Corregimos el del loadVideo() - loadVideo(); //Cargamos la nueva calidad + break; } } - else if((bps > qualities.get(currentQuality).getQuality()) && (bps != -1)) + if(currentQuality != newQuality) { - int newQuality; - for(newQuality = qualities.size()-1; newQuality > 0; newQuality--) - { - if(bps <= qualities.get(newQuality).getQuality()) - { - newQuality--; - break; - } - } - if(currentQuality != newQuality) + currentQuality = newQuality; + currentVideo--; //Corregimos el del loadVideo() + loadVideo(); //Cargamos la nueva calidad + } + } + else if((bps > qualities.get(currentQuality).getQuality()) && (bps != -1)) + { + int newQuality; + for(newQuality = qualities.size()-1; newQuality > 0; newQuality--) + { + if(bps <= qualities.get(newQuality).getQuality()) { - currentQuality = newQuality; - currentVideo--; //Corregimos el del loadVideo() - loadVideo(); //Cargamos la nueva calidad + newQuality--; + break; } } + if(currentQuality != newQuality) + { + currentQuality = newQuality; + currentVideo--; //Corregimos el del loadVideo() + loadVideo(); //Cargamos la nueva calidad + } } - return path; - } - - public void descarregarguardar(String url, String path) - { - Request req = new Request(Uri.parse(url)); - req.setVisibleInDownloadsUi(false); - req.setDestinationUri(Uri.parse("file://"+path + url.substring(url.lastIndexOf("/")+1, url.length()))); - dm.enqueue(req); } public String previous() throws IOException @@ -136,9 +175,127 @@ public class HLS seg = segments.get(currentSegment++); return localFolder + seg.getURL().substring(seg.getURL().lastIndexOf("/") + 1, seg.getURL().length()); } - - public void startDownloadManager(Context ctx) + + public boolean hasEnded() + { + return ended; + } + + public void buffer() + { + video.stopPlayback(); + started = false; + } + + public void downloadSegment(String url) { - dm = (DownloadManager) ctx.getSystemService("download"); + DescarregaSegment ds = new DescarregaSegment(vActivity); + try + { + ds.execute(new URL(url)); + } + catch (MalformedURLException e) + { + e.printStackTrace(); + } + } + + public class DescarregaSegment extends AsyncTask + { + final static String TAG = "DescarregaSegment"; + private Context ctx; + private long bps; + AlertDialog alertDialog; + + public DescarregaSegment(Context c) + { + ctx = c; + bps = 0; + AlertDialog.Builder builder = new AlertDialog.Builder(vActivity); + LayoutInflater inflater = vActivity.getLayoutInflater(); + builder.setView(inflater.inflate(R.layout.buffering_dialog,null)); + alertDialog = builder.create(); + } + + + @Override + protected Long doInBackground(URL... urls) + { + if(!started) + { + alertDialog.show(); + } + Long downloaded = Long.valueOf(0); + long startTime = System.currentTimeMillis(); + long segmentBytes = TrafficStats.getTotalRxBytes(); + Log.d(TAG, "Velocitat actual (KB/s): " + (bps / 8e3)); + // Iniciem la connexi� i creem els Streams + try + { + FileOutputStream out = new FileOutputStream(localFolder + "video.ts"); + BufferedInputStream in = new BufferedInputStream(urls[0].openStream()); + Log.d(TAG, "\nDescarregant: \n"); + Log.d(TAG, ">> URL: " + urls[0]); + byte data[] = new byte[102400]; + int count; + while ((count = in.read(data)) != -1) + { + downloaded += count; + out.write(data, 0, count); + } + out.flush(); + out.close(); + in.close(); + bps = (long) bm.Measure(segmentBytes, startTime); + Log.d(TAG, "Descarrega finalitzada"); + } + catch(IOException e) + { + this.cancel(true); + Toast.makeText(ctx, e.getMessage(), Toast.LENGTH_LONG).show(); + return Long.valueOf(-1); + } + return downloaded; + } + protected void onPostExecute(Long result) + { + totalDownloaded += result; + if(ended = true) + { + quitPlayer((VideoActivity) ctx); + } + if(TRIGGER_PLAY == -1) + { + long Bps = (long) (result/segments.get(currentSegment).getDuration()); + TRIGGER_PLAY = 15*Bps/1000; + } + if(!started && totalDownloaded >= TRIGGER_PLAY) + { + alertDialog.dismiss(); + started = true; + video.start(); + video.requestFocus(); + } + String newSegment = null; + try + { + updateQuality((long) bps); + newSegment = next(); + } + catch(IOException e) + { + Toast.makeText(ctx, "No s'ha trobat el segment", Toast.LENGTH_LONG).show(); + quitPlayer((VideoActivity) ctx); + } + if(newSegment.equals(null)) + { + ended = true; + } + else + { + downloadSegment(newSegment); + } + return; + } } } \ No newline at end of file diff --git a/src/com/upc/pbe/upcnews/MainActivity.java b/src/com/upc/pbe/upcnews/MainActivity.java index 9a90def..73ca1ad 100644 --- a/src/com/upc/pbe/upcnews/MainActivity.java +++ b/src/com/upc/pbe/upcnews/MainActivity.java @@ -21,7 +21,8 @@ import android.widget.TextView; import android.widget.Toast; //Finestra incial i activity principal del programa -public class MainActivity extends Activity implements OnClickListener { +public class MainActivity extends Activity implements OnClickListener +{ private final static String TAG = "Main"; private static String html; @@ -78,19 +79,18 @@ public class MainActivity extends Activity implements OnClickListener { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { Toast.makeText(this, "URL Malformada", Toast.LENGTH_LONG).show(); } - if(!html.equals("")) { + if(!html.equals("")) + { ((UpcApp) getApplication()).setDesc(html); startActivity(new Intent(this, Directoris.class)); } diff --git a/src/com/upc/pbe/upcnews/ParentList.java b/src/com/upc/pbe/upcnews/ParentList.java index 056df6e..a1748b3 100644 --- a/src/com/upc/pbe/upcnews/ParentList.java +++ b/src/com/upc/pbe/upcnews/ParentList.java @@ -5,7 +5,6 @@ import java.util.ArrayList; public class ParentList { private String ID; - private int currentQuality; private String Type, Name; private boolean Default; //Estos 3 ultimos son para los ext-x-media, los ext-x-stream lo IGNORAN private ArrayList