Commit 9419e4f97245b66726eaf119f5d0887c9b270f3b

Authored by Imanol-Mikel Barba Sabariego
1 parent bd6acc35

Release Candidate (intentaré implementar reproducción continua, sino, nos quedam…

…os con esto, TODAS LAS MODIFICACIONS SE HARÁN A PARTIR DE AQUÍ
src/com/upc/pbe/upcnews/BandwidthMeasurer.java
@@ -18,6 +18,7 @@ public class BandwidthMeasurer @@ -18,6 +18,7 @@ public class BandwidthMeasurer
18 Log.d(TAG, "Diferencia de bytes = " + rxDiff); 18 Log.d(TAG, "Diferencia de bytes = " + rxDiff);
19 if(rxDiff != 0){ 19 if(rxDiff != 0){
20 bps = ((rxDiff*8) / (TimeDifference/1000)); // total de rx en bits per second. 20 bps = ((rxDiff*8) / (TimeDifference/1000)); // total de rx en bits per second.
  21 + Log.d(TAG, "Velocitat actual (KB/s): " + (bps / 8e3));
21 } 22 }
22 else{ 23 else{
23 bps = -1; //No s'han trasmes dades 24 bps = -1; //No s'han trasmes dades
src/com/upc/pbe/upcnews/HLS.java
1 package com.upc.pbe.upcnews; 1 package com.upc.pbe.upcnews;
2 2
3 -import io.vov.vitamio.widget.VideoView;  
4 -  
5 -import java.io.BufferedInputStream;  
6 import java.io.File; 3 import java.io.File;
7 -import java.io.FileOutputStream;  
8 import java.io.IOException; 4 import java.io.IOException;
9 -import java.net.MalformedURLException;  
10 -import java.net.URL;  
11 import java.util.ArrayList; 5 import java.util.ArrayList;
12 6
13 -import android.app.AlertDialog;  
14 -import android.content.Context;  
15 -import android.net.TrafficStats;  
16 -import android.os.AsyncTask;  
17 import android.util.Log; 7 import android.util.Log;
18 -import android.view.LayoutInflater;  
19 -import android.widget.Toast;  
20 8
21 //Gestor del protocol HTTP Live Streaming 9 //Gestor del protocol HTTP Live Streaming
22 public class HLS 10 public class HLS
23 { 11 {
24 - private static long TRIGGER_PLAY; 12 +
25 private static final String TAG = "HLS"; 13 private static final String TAG = "HLS";
26 private ArrayList<ParentList> videos; 14 private ArrayList<ParentList> videos;
27 private ArrayList<Segment> segments; 15 private ArrayList<Segment> segments;
@@ -30,14 +18,6 @@ public class HLS @@ -30,14 +18,6 @@ public class HLS
30 private int currentQuality; // 0 es la mas alta 18 private int currentQuality; // 0 es la mas alta
31 private int currentSegment; 19 private int currentSegment;
32 private boolean endReached; 20 private boolean endReached;
33 - private String localFolder;  
34 - private BandwidthMeasurer bm;  
35 - private boolean started;  
36 - private boolean ended;  
37 - private long totalDownloaded;  
38 - private VideoView video;  
39 - private VideoActivity vActivity;  
40 -  
41 21
42 public HLS(ArrayList<ParentList> parsed, String localFolder) 22 public HLS(ArrayList<ParentList> parsed, String localFolder)
43 { 23 {
@@ -54,47 +34,6 @@ public class HLS @@ -54,47 +34,6 @@ public class HLS
54 currentVideo = currentQuality = currentSegment = 0; 34 currentVideo = currentQuality = currentSegment = 0;
55 this.videos = parsed; 35 this.videos = parsed;
56 endReached = false; 36 endReached = false;
57 - this.localFolder = localFolder;  
58 - bm = new BandwidthMeasurer();  
59 - started = ended = false;  
60 - totalDownloaded = 0;  
61 - }  
62 -  
63 - public void setBufferSize()  
64 - {  
65 - /*  
66 - * Supondremos todos los segmentos de misma duración  
67 - */  
68 - if(qualities.get(currentQuality).getQuality() == -1)  
69 - {  
70 - /*  
71 - * No nos dicen la calidad, la pondremos al conocer la longitud del primer segmento  
72 - */  
73 - TRIGGER_PLAY = -1;  
74 - }  
75 - else  
76 - {  
77 - //15 segundos de cancha para empezar  
78 - TRIGGER_PLAY = (long) (15 * qualities.get(currentQuality).getQuality()/8e3);  
79 - }  
80 -  
81 - }  
82 -  
83 - public void quitPlayer(VideoActivity v)  
84 - {  
85 - video.stopPlayback();  
86 - v.finish();  
87 - return;  
88 - }  
89 -  
90 - public void setVideoViewer(VideoView v)  
91 - {  
92 - video = v;  
93 - }  
94 -  
95 - public void setVideoActivity(VideoActivity v)  
96 - {  
97 - vActivity = v;  
98 } 37 }
99 38
100 public void loadVideo() 39 public void loadVideo()
@@ -106,7 +45,6 @@ public class HLS @@ -106,7 +45,6 @@ public class HLS
106 { 45 {
107 endReached = true; 46 endReached = true;
108 } 47 }
109 - setBufferSize();  
110 } 48 }
111 49
112 public String next() throws IOException 50 public String next() throws IOException
@@ -121,9 +59,13 @@ public class HLS @@ -121,9 +59,13 @@ public class HLS
121 loadVideo(); 59 loadVideo();
122 } 60 }
123 Segment seg = segments.get(currentSegment++); 61 Segment seg = segments.get(currentSegment++);
124 - String path = localFolder+seg.getURL().substring(seg.getURL().lastIndexOf("/") + 1, seg.getURL().length());  
125 Log.d(TAG, seg.getName() + " " + seg.getURL()); 62 Log.d(TAG, seg.getName() + " " + seg.getURL());
126 - return path; 63 + return seg.getURL();
  64 + }
  65 +
  66 + public long getCurrentSegmentDuration()
  67 + {
  68 + return (long) segments.get(currentSegment).getDuration();
127 } 69 }
128 70
129 public void updateQuality(long bps) 71 public void updateQuality(long bps)
@@ -165,137 +107,5 @@ public class HLS @@ -165,137 +107,5 @@ public class HLS
165 } 107 }
166 } 108 }
167 109
168 - public String previous() throws IOException  
169 - {  
170 - Segment seg = null;  
171 - if (--currentSegment > 0)  
172 - {  
173 - --currentSegment;  
174 - }  
175 - seg = segments.get(currentSegment++);  
176 - return localFolder + seg.getURL().substring(seg.getURL().lastIndexOf("/") + 1, seg.getURL().length());  
177 - }  
178 -  
179 - public boolean hasEnded()  
180 - {  
181 - return ended;  
182 - }  
183 -  
184 - public void buffer()  
185 - {  
186 - video.stopPlayback();  
187 - started = false;  
188 - }  
189 -  
190 - public void downloadSegment(String url)  
191 - {  
192 - DescarregaSegment ds = new DescarregaSegment(vActivity);  
193 - try  
194 - {  
195 - ds.execute(new URL(url));  
196 - }  
197 - catch (MalformedURLException e)  
198 - {  
199 - e.printStackTrace();  
200 - }  
201 - }  
202 110
203 - public class DescarregaSegment extends AsyncTask<URL, Integer, Long>  
204 - {  
205 - final static String TAG = "DescarregaSegment";  
206 - private Context ctx;  
207 - private long bps;  
208 - AlertDialog alertDialog;  
209 -  
210 - public DescarregaSegment(Context c)  
211 - {  
212 - ctx = c;  
213 - bps = 0;  
214 - AlertDialog.Builder builder = new AlertDialog.Builder(vActivity);  
215 - LayoutInflater inflater = vActivity.getLayoutInflater();  
216 - builder.setView(inflater.inflate(R.layout.buffering_dialog,null));  
217 - alertDialog = builder.create();  
218 - }  
219 -  
220 -  
221 - @Override  
222 - protected Long doInBackground(URL... urls)  
223 - {  
224 - if(!started)  
225 - {  
226 - alertDialog.show();  
227 - }  
228 - Long downloaded = Long.valueOf(0);  
229 - long startTime = System.currentTimeMillis();  
230 - long segmentBytes = TrafficStats.getTotalRxBytes();  
231 - Log.d(TAG, "Velocitat actual (KB/s): " + (bps / 8e3));  
232 - // Iniciem la connexi� i creem els Streams  
233 - try  
234 - {  
235 - FileOutputStream out = new FileOutputStream(localFolder + "video.ts");  
236 - BufferedInputStream in = new BufferedInputStream(urls[0].openStream());  
237 - Log.d(TAG, "\nDescarregant: \n");  
238 - Log.d(TAG, ">> URL: " + urls[0]);  
239 - byte data[] = new byte[102400];  
240 - int count;  
241 - while ((count = in.read(data)) != -1)  
242 - {  
243 - downloaded += count;  
244 - out.write(data, 0, count);  
245 - }  
246 - out.flush();  
247 - out.close();  
248 - in.close();  
249 - bps = (long) bm.Measure(segmentBytes, startTime);  
250 - Log.d(TAG, "Descarrega finalitzada");  
251 - }  
252 - catch(IOException e)  
253 - {  
254 - this.cancel(true);  
255 - Toast.makeText(ctx, e.getMessage(), Toast.LENGTH_LONG).show();  
256 - return Long.valueOf(-1);  
257 - }  
258 - return downloaded;  
259 - }  
260 - protected void onPostExecute(Long result)  
261 - {  
262 - totalDownloaded += result;  
263 - if(ended = true)  
264 - {  
265 - quitPlayer((VideoActivity) ctx);  
266 - }  
267 - if(TRIGGER_PLAY == -1)  
268 - {  
269 - long Bps = (long) (result/segments.get(currentSegment).getDuration());  
270 - TRIGGER_PLAY = 15*Bps/1000;  
271 - }  
272 - if(!started && totalDownloaded >= TRIGGER_PLAY)  
273 - {  
274 - alertDialog.dismiss();  
275 - started = true;  
276 - video.start();  
277 - video.requestFocus();  
278 - }  
279 - String newSegment = null;  
280 - try  
281 - {  
282 - updateQuality((long) bps);  
283 - newSegment = next();  
284 - }  
285 - catch(IOException e)  
286 - {  
287 - Toast.makeText(ctx, "No s'ha trobat el segment", Toast.LENGTH_LONG).show();  
288 - quitPlayer((VideoActivity) ctx);  
289 - }  
290 - if(newSegment.equals(null))  
291 - {  
292 - ended = true;  
293 - }  
294 - else  
295 - {  
296 - downloadSegment(newSegment);  
297 - }  
298 - return;  
299 - }  
300 - }  
301 } 111 }
302 \ No newline at end of file 112 \ No newline at end of file
src/com/upc/pbe/upcnews/VideoActivity.java
1 package com.upc.pbe.upcnews; 1 package com.upc.pbe.upcnews;
2 2
3 import io.vov.vitamio.MediaPlayer; 3 import io.vov.vitamio.MediaPlayer;
  4 +import io.vov.vitamio.R;
4 import io.vov.vitamio.widget.MediaController; 5 import io.vov.vitamio.widget.MediaController;
5 import io.vov.vitamio.widget.VideoView; 6 import io.vov.vitamio.widget.VideoView;
6 7
  8 +import java.io.BufferedInputStream;
  9 +import java.io.FileOutputStream;
7 import java.io.IOException; 10 import java.io.IOException;
  11 +import java.net.MalformedURLException;
  12 +import java.net.URL;
  13 +import java.util.ArrayList;
8 14
9 import android.app.Activity; 15 import android.app.Activity;
  16 +import android.app.ProgressDialog;
10 import android.content.res.Configuration; 17 import android.content.res.Configuration;
  18 +import android.net.TrafficStats;
  19 +import android.os.AsyncTask;
11 import android.os.Bundle; 20 import android.os.Bundle;
12 import android.util.Log; 21 import android.util.Log;
13 import android.view.View; 22 import android.view.View;
@@ -20,6 +29,13 @@ public class VideoActivity extends Activity { @@ -20,6 +29,13 @@ public class VideoActivity extends Activity {
20 private VideoView video; 29 private VideoView video;
21 private HLS h = null; 30 private HLS h = null;
22 private String filePath; 31 private String filePath;
  32 + private BandwidthMeasurer bm;
  33 + private ProgressDialog pd;
  34 + ArrayList<String> queue;
  35 + ArrayList<String> playedQueue;
  36 + int currentPos;
  37 + boolean ended;
  38 + boolean buffering;
23 39
24 40
25 @Override 41 @Override
@@ -33,49 +49,44 @@ public class VideoActivity extends Activity { @@ -33,49 +49,44 @@ public class VideoActivity extends Activity {
33 { 49 {
34 return; 50 return;
35 } 51 }
36 -  
37 setContentView(R.layout.activity_video); 52 setContentView(R.layout.activity_video);
38 - filePath = ((UpcApp)getApplication()).getLocalPath() + "video.ts"; 53 + currentPos = 0;
  54 + queue = new ArrayList<String>();
  55 + playedQueue = new ArrayList<String>();
  56 + buffering = true;
  57 + ended = false;
  58 + filePath = ((UpcApp)getApplication()).getLocalPath();
39 video = (VideoView) findViewById(R.id.VideoView1); 59 video = (VideoView) findViewById(R.id.VideoView1);
40 //Creem un listener associat al fi de l'activitat (el fi de cada ts) 60 //Creem un listener associat al fi de l'activitat (el fi de cada ts)
41 io.vov.vitamio.widget.MediaController mc = new MediaController(this); 61 io.vov.vitamio.widget.MediaController mc = new MediaController(this);
42 video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 62 video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
43 public void onCompletion(MediaPlayer mp) { 63 public void onCompletion(MediaPlayer mp) {
44 //Al acabar cada ts, reproduit el seguent 64 //Al acabar cada ts, reproduit el seguent
45 - if(h.hasEnded())  
46 - {  
47 - finish();  
48 - return;  
49 - }  
50 - h.buffer(); 65 + playNext();
51 } 66 }
52 }); 67 });
53 mc.setOnFFLeftListener(new View.OnClickListener() { 68 mc.setOnFFLeftListener(new View.OnClickListener() {
54 public void onClick(View v) { 69 public void onClick(View v) {
55 Log.d(TAG, "FFLEFT"); 70 Log.d(TAG, "FFLEFT");
56 - video.seekTo(-100); 71 + playPrevious();
57 } 72 }
58 }); 73 });
59 mc.setOnFFRightListener(new View.OnClickListener() { 74 mc.setOnFFRightListener(new View.OnClickListener() {
60 public void onClick(View v) { 75 public void onClick(View v) {
61 Log.d(TAG, "FFRIGHT"); 76 Log.d(TAG, "FFRIGHT");
62 - video.stopPlayback();  
63 playNext(); 77 playNext();
64 } 78 }
65 }); 79 });
66 video.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH); 80 video.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);
67 //Creem un gestor HLS, carreguem el video i iniciem la reproduccio 81 //Creem un gestor HLS, carreguem el video i iniciem la reproduccio
68 h = ((UpcApp)getApplication()).getHLS(); 82 h = ((UpcApp)getApplication()).getHLS();
69 - h.setVideoViewer(video);  
70 - h.setVideoActivity(this);  
71 h.loadVideo(); 83 h.loadVideo();
72 - video.stopPlayback();  
73 video.setMediaController(mc); 84 video.setMediaController(mc);
74 - video.setVideoPath("file://" + filePath);  
75 - h.downloadSegment(playNext()); 85 + bm = new BandwidthMeasurer();
  86 + downloadSegment(getNext());
76 } 87 }
77 88
78 - public String playNext() { 89 + public String getNext() {
79 try { 90 try {
80 return h.next(); 91 return h.next();
81 } 92 }
@@ -85,16 +96,95 @@ public class VideoActivity extends Activity { @@ -85,16 +96,95 @@ public class VideoActivity extends Activity {
85 return ""; 96 return "";
86 } 97 }
87 } 98 }
88 - public void playPrevious() {  
89 - try {  
90 - String prev = h.previous();  
91 - //play(prev); 99 +
  100 + public void toggleBuffering(boolean b)
  101 + {
  102 + if(b)
  103 + {
  104 + pd = new ProgressDialog(VideoActivity.this);
  105 + pd.setCancelable(false);
  106 + pd.setMessage(getString(R.string.buffering_text));
  107 + pd.show();
92 } 108 }
93 - catch(IOException e) {  
94 - Toast.makeText(this, "No s'ha trobat el segment", Toast.LENGTH_LONG).show();  
95 - super.finish(); 109 + else if(pd != null)
  110 + {
  111 + pd.dismiss();
  112 + pd = null;
  113 + }
  114 + }
  115 +
  116 + public void quitPlayer()
  117 + {
  118 + video.stopPlayback();
  119 + super.finish();
  120 + return;
  121 + }
  122 +
  123 + public void buffer()
  124 + {
  125 + buffering = true;
  126 + video.suspend();
  127 + }
  128 + public void play(String path)
  129 + {
  130 + toggleBuffering(false);
  131 + video.setVideoPath(path);
  132 + video.start();
  133 + video.requestFocus();
  134 + }
  135 +
  136 + public void playNext()
  137 + {
  138 + if(++currentPos > 0)
  139 + {
  140 + currentPos = 0;
  141 + }
  142 + if(currentPos == 0)
  143 + {
  144 + playedQueue.add(queue.get(0));
  145 + queue.remove(0);
  146 + if(ended && queue.isEmpty())
  147 + {
  148 + VideoActivity.super.finish();
  149 + return;
  150 + }
  151 + if(queue.isEmpty())
  152 + {
  153 + buffer();
  154 + }
  155 + play(queue.get(0));
  156 + }
  157 + else if(currentPos < 0)
  158 + {
  159 + play(playedQueue.get(playedQueue.size() + currentPos));
  160 + }
  161 + }
  162 +
  163 + public void playPrevious()
  164 + {
  165 + if(playedQueue.isEmpty())
  166 + {
  167 + play(queue.get(0));
96 return; 168 return;
97 } 169 }
  170 + else if(playedQueue.size() + (--currentPos) < 0)
  171 + {
  172 + currentPos++;
  173 + }
  174 + play(playedQueue.get(playedQueue.size() + currentPos));
  175 + }
  176 +
  177 + public void downloadSegment(String url)
  178 + {
  179 + DescarregaSegment ds = new DescarregaSegment();
  180 + try
  181 + {
  182 + ds.execute(new URL(url));
  183 + }
  184 + catch (MalformedURLException e)
  185 + {
  186 + e.printStackTrace();
  187 + }
98 } 188 }
99 189
100 @Override 190 @Override
@@ -104,4 +194,87 @@ public class VideoActivity extends Activity { @@ -104,4 +194,87 @@ public class VideoActivity extends Activity {
104 super.onConfigurationChanged(newConfig); 194 super.onConfigurationChanged(newConfig);
105 } 195 }
106 196
  197 + public class DescarregaSegment extends AsyncTask<URL, Void, Void>
  198 + {
  199 + final static String TAG = "DescarregaSegment";
  200 + private long bps;
  201 +
  202 + public DescarregaSegment()
  203 + {
  204 + bps = 0;
  205 + pd = null;
  206 + }
  207 +
  208 + @Override
  209 + protected void onPreExecute()
  210 + {
  211 + if(queue.isEmpty() && !ended)
  212 + {
  213 + toggleBuffering(true);
  214 + }
  215 + }
  216 +
  217 + @Override
  218 + protected Void doInBackground(URL... urls)
  219 + {
  220 + Long downloaded = Long.valueOf(0);
  221 + long startTime = System.currentTimeMillis();
  222 + long segmentBytes = TrafficStats.getTotalRxBytes();
  223 + String fileName = urls[0].toString().substring(urls[0].toString().lastIndexOf("/"));
  224 + // Iniciem la connexi� i creem els Streams
  225 + try
  226 + {
  227 + FileOutputStream out = new FileOutputStream(filePath + fileName,true);
  228 + BufferedInputStream in = new BufferedInputStream(urls[0].openStream());
  229 + Log.d(TAG, "\nDescarregant: \n");
  230 + Log.d(TAG, ">> URL: " + urls[0]);
  231 + byte data[] = new byte[102400];
  232 + int count;
  233 + while ((count = in.read(data)) != -1)
  234 + {
  235 + downloaded += count;
  236 + out.write(data, 0, count);
  237 + }
  238 + out.flush();
  239 + out.close();
  240 + in.close();
  241 + bps = (long) bm.Measure(segmentBytes, startTime);
  242 + Log.d(TAG, "Descarrega finalitzada");
  243 + queue.add(filePath + fileName);
  244 + }
  245 + catch(IOException e)
  246 + {
  247 + this.cancel(true);
  248 + Toast.makeText(VideoActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
  249 + return null;
  250 + }
  251 + return null;
  252 + }
  253 + protected void onPostExecute(Void v)
  254 + {
  255 + if(ended)
  256 + {
  257 + return;
  258 + }
  259 +
  260 + if(!queue.isEmpty() && buffering)
  261 + {
  262 + buffering = false;
  263 + play(queue.get(0));
  264 + }
  265 + String newSegment = null;
  266 + h.updateQuality((long) bps);
  267 + newSegment = getNext();
  268 + if(newSegment == null)
  269 + {
  270 + ended = true;
  271 + }
  272 + else
  273 + {
  274 + downloadSegment(newSegment);
  275 + }
  276 + return;
  277 + }
  278 + }
  279 +
107 } 280 }
108 \ No newline at end of file 281 \ No newline at end of file