diff --git a/pom.xml b/pom.xml index a5d136bca..f0795de2b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,8 +3,22 @@ 4.0.0 com.tonikelope MegaBasterd - 7.61 + 7.62 jar + + + olivier-ayache-xuggler + https://dl.cloudsmith.io/public/olivier-ayache/xuggler/maven/ + + true + always + + + true + always + + + org.xerial @@ -39,6 +53,11 @@ jackson-databind 2.12.6.1 + + xuggle + xuggle-xuggler-server-all + 5.7.0-SNAPSHOT + UTF-8 diff --git a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form index b3c8000ff..ffc10c15c 100644 --- a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form +++ b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form @@ -285,7 +285,6 @@ - diff --git a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java index fd3451b3b..9e6eb71d0 100644 --- a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java +++ b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java @@ -330,7 +330,6 @@ public class FileGrabberDialog extends javax.swing.JDialog { }); upload_log_checkbox.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N - upload_log_checkbox.setSelected(true); upload_log_checkbox.setText("Enable log file"); upload_log_checkbox.setDoubleBuffered(true); upload_log_checkbox.setEnabled(false); diff --git a/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java b/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java index 924c756e6..cb3407d89 100644 --- a/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java +++ b/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java @@ -891,6 +891,7 @@ public class LabelTranslatorSingleton { _addTranslation("Execute this command when MEGA download limit is reached:", "Ejecutar este comando cuando se alcance el límite de descarga de MEGA:"); _addTranslation("Use this proxy list (instead of the one included in MegaBasterd) Format is [*]IP:PORT[@user_b64:password_b64]", "Usar esta lista de proxys (en vez de la incluida en MegaBasterd) El formato es [*]IP:PUERTO[@usuario_b64:password_b64]"); _addTranslation("Waiting for completion handler ... ***DO NOT EXIT MEGABASTERD NOW***", "Esperando manejador de finalización ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***"); + _addTranslation("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***", "Creando y subiendo thumbnails ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***"); _addTranslation("Finishing calculating CBC-MAC code (this could take a while) ... ***DO NOT EXIT MEGABASTERD NOW***", "Terminando de calcular código CBC-MAC (esto podría llevar tiempo) ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***"); _addTranslation("Split content in different uploads", "Separar contenido en diferentes subidas"); _addTranslation("Merge content in the same upload", "Juntar todo en la misma subida"); diff --git a/src/main/java/com/tonikelope/megabasterd/MainPanel.java b/src/main/java/com/tonikelope/megabasterd/MainPanel.java index b6bd97e6a..d288c2de0 100644 --- a/src/main/java/com/tonikelope/megabasterd/MainPanel.java +++ b/src/main/java/com/tonikelope/megabasterd/MainPanel.java @@ -67,7 +67,7 @@ import javax.swing.UIManager; */ public final class MainPanel { - public static final String VERSION = "7.61"; + public static final String VERSION = "7.62"; public static final boolean FORCE_SMART_PROXY = false; //TRUE FOR DEBUGING SMART PROXY public static final int THROTTLE_SLICE_SIZE = 16 * 1024; public static final int DEFAULT_BYTE_BUFFER_SIZE = 16 * 1024; diff --git a/src/main/java/com/tonikelope/megabasterd/MegaAPI.java b/src/main/java/com/tonikelope/megabasterd/MegaAPI.java index d0d0110e8..fee057954 100644 --- a/src/main/java/com/tonikelope/megabasterd/MegaAPI.java +++ b/src/main/java/com/tonikelope/megabasterd/MegaAPI.java @@ -17,12 +17,15 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.Serializable; import java.math.BigInteger; +import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -634,6 +637,19 @@ public class MegaAPI implements Serializable { return file_data; } + private byte[] _encThumbAttr(byte[] attr_byte, byte[] key) { + + try { + + return aes_cbc_encrypt_pkcs7(attr_byte, key, AES_ZERO_IV); + + } catch (Exception ex) { + LOG.log(Level.SEVERE, ex.getMessage()); + } + + return null; + } + private byte[] _encAttr(String attr, byte[] key) { byte[] ret = null; @@ -714,6 +730,115 @@ public class MegaAPI implements Serializable { return ul_url; } + public String uploadThumbnails(Upload upload, String node_handle, String filename0, String filename1) throws MegaAPIException { + + String[] ul_url = new String[2]; + + String[] hash = new String[2]; + + try { + + File[] files = new File[2]; + + files[0] = new File(filename0); + + byte[][] file_bytes = new byte[2][]; + + file_bytes[0] = _encThumbAttr(Files.readAllBytes(files[0].toPath()), upload.getByte_file_key()); + + files[1] = new File(filename1); + + file_bytes[1] = _encThumbAttr(Files.readAllBytes(files[1].toPath()), upload.getByte_file_key()); + + String request = "[{\"a\":\"ufa\", \"s\":" + String.valueOf(file_bytes[0].length) + ", \"ssl\":1}, {\"a\":\"ufa\", \"s\":" + String.valueOf(file_bytes[1].length) + ", \"ssl\":1}]"; + + System.out.println(request); + URL url_api = new URL(API_URL + "/cs?id=" + String.valueOf(_seqno) + (_sid != null ? "&sid=" + _sid : "") + (API_KEY != null ? "&ak=" + API_KEY : "")); + + String res = _rawRequest(request, url_api); + + System.out.println(res); + + ObjectMapper objectMapper = new ObjectMapper(); + + HashMap[] res_map = objectMapper.readValue(res, HashMap[].class); + + ul_url[0] = (String) res_map[0].get("p"); + + ul_url[1] = (String) res_map[1].get("p"); + + int h = 0; + + for (String u : ul_url) { + + URL url = new URL(u); + + HttpURLConnection con; + + con = (HttpURLConnection) url.openConnection(); + + con.setConnectTimeout(Transference.HTTP_CONNECT_TIMEOUT); + + con.setReadTimeout(Transference.HTTP_READ_TIMEOUT); + + con.setRequestMethod("POST"); + + con.setDoOutput(true); + + con.setUseCaches(false); + + con.setRequestProperty("User-Agent", MainPanel.DEFAULT_USER_AGENT); + + byte[] buffer = new byte[8192]; + + int reads; + + try ( OutputStream out = new ThrottledOutputStream(con.getOutputStream(), upload.getMain_panel().getStream_supervisor())) { + + out.write(file_bytes[h]); + } + + try ( InputStream is = con.getInputStream(); ByteArrayOutputStream byte_res = new ByteArrayOutputStream()) { + + while ((reads = is.read(buffer)) != -1) { + byte_res.write(buffer, 0, reads); + } + + hash[h] = MiscTools.Bin2UrlBASE64(byte_res.toByteArray()); + + System.out.println(hash[h]); + } + + h++; + } + + request = "[{\"a\":\"pfa\", \"fa\":\"0*" + hash[0] + "/1*" + hash[1] + "\", \"n\":\"" + node_handle + "\"}]"; + + url_api = new URL(API_URL + "/cs?id=" + String.valueOf(_seqno) + (_sid != null ? "&sid=" + _sid : "") + (API_KEY != null ? "&ak=" + API_KEY : "")); + + res = _rawRequest(request, url_api); + + System.out.println(request); + + objectMapper = new ObjectMapper(); + + String[] resp = objectMapper.readValue(res, String[].class); + + System.out.println((String) resp[0]); + + return (String) resp[0]; + + } catch (MegaAPIException mae) { + + throw mae; + + } catch (Exception ex) { + LOG.log(Level.SEVERE, ex.getMessage()); + } + + return ""; + } + public HashMap finishUploadFile(String fbasename, int[] ul_key, int[] fkey, int[] meta_mac, String completion_handle, String mega_parent, byte[] master_key, String root_node, byte[] share_key) throws MegaAPIException { HashMap[] res_map = null; diff --git a/src/main/java/com/tonikelope/megabasterd/MiscTools.java b/src/main/java/com/tonikelope/megabasterd/MiscTools.java index f128beb6f..9aee06d7d 100644 --- a/src/main/java/com/tonikelope/megabasterd/MiscTools.java +++ b/src/main/java/com/tonikelope/megabasterd/MiscTools.java @@ -17,12 +17,15 @@ import java.awt.Dialog; import java.awt.Font; import java.awt.FontFormatException; import java.awt.Frame; +import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; +import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; +import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -126,6 +129,28 @@ public class MiscTools { return getFechaHoraActual(format); } + public static boolean isVideoFile(Path path) { + + try { + return Files.probeContentType(path).startsWith("video/"); + } catch (IOException ex) { + Logger.getLogger(MiscTools.class.getName()).log(Level.SEVERE, null, ex); + } + + return false; + } + + public static boolean isImageFile(Path path) { + + try { + return Files.probeContentType(path).startsWith("image/"); + } catch (IOException ex) { + Logger.getLogger(MiscTools.class.getName()).log(Level.SEVERE, null, ex); + } + + return false; + } + public static String getFechaHoraActual(String format) { Date currentDate = new Date(System.currentTimeMillis()); @@ -241,6 +266,23 @@ public class MiscTools { return bigi; } + public static BufferedImage toBufferedImage(Image img) { + if (img instanceof BufferedImage) { + return (BufferedImage) img; + } + + // Create a buffered image with transparency + BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); + + // Draw the image on to the buffered image + Graphics2D bGr = bimage.createGraphics(); + bGr.drawImage(img, 0, 0, null); + bGr.dispose(); + + // Return the buffered image + return bimage; + } + public static String genID(int length) { String pos = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java b/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java index 65aa01cb0..c0fe823ac 100644 --- a/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java +++ b/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java @@ -2049,7 +2049,7 @@ public class SettingsDialog extends javax.swing.JDialog { boolean error_2FA = false; - if (ma.check2FA(email)) { + if (!_main_panel.getMega_active_accounts().containsKey(email) && ma.check2FA(email)) { Get2FACode dialog = new Get2FACode((Frame) getParent(), true, email, _main_panel); @@ -2065,37 +2065,40 @@ public class SettingsDialog extends javax.swing.JDialog { } if (!error_2FA) { - ma.login(email, pass, pincode); + if (!_main_panel.getMega_active_accounts().containsKey(email)) { + ma.login(email, pass, pincode); - ByteArrayOutputStream bs = new ByteArrayOutputStream(); + ByteArrayOutputStream bs = new ByteArrayOutputStream(); - try ( ObjectOutputStream os = new ObjectOutputStream(bs)) { - os.writeObject(ma); + try ( ObjectOutputStream os = new ObjectOutputStream(bs)) { + os.writeObject(ma); + } + + if (_main_panel.getMaster_pass() != null) { + + DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true); + + } else { + + DBTools.insertMegaSession(email, bs.toByteArray(), false); + } + + _main_panel.getMega_active_accounts().put(email, ma); + + String password = pass, password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash(); + + if (_main_panel.getMaster_pass_hash() != null) { + + password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + + password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + + user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + } + + DBTools.insertMegaAccount(email, password, password_aes, user_hash); } - if (_main_panel.getMaster_pass() != null) { - - DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true); - - } else { - - DBTools.insertMegaSession(email, bs.toByteArray(), false); - } - - _main_panel.getMega_active_accounts().put(email, ma); - - String password = pass, password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash(); - - if (_main_panel.getMaster_pass_hash() != null) { - - password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - - password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - - user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - } - - DBTools.insertMegaAccount(email, password, password_aes, user_hash); } else { email_error.add(email); } @@ -2133,7 +2136,7 @@ public class SettingsDialog extends javax.swing.JDialog { boolean error_2FA = false; - if (ma.check2FA(email)) { + if (!_main_panel.getMega_active_accounts().containsKey(email) && ma.check2FA(email)) { Get2FACode dialog = new Get2FACode((Frame) getParent(), true, email, _main_panel); @@ -2149,40 +2152,41 @@ public class SettingsDialog extends javax.swing.JDialog { } if (!error_2FA) { + if (!_main_panel.getMega_active_accounts().containsKey(email)) { + ma.login(email, pass, pincode); - ma.login(email, pass, pincode); + ByteArrayOutputStream bs = new ByteArrayOutputStream(); - ByteArrayOutputStream bs = new ByteArrayOutputStream(); + try ( ObjectOutputStream os = new ObjectOutputStream(bs)) { + os.writeObject(ma); + } - try ( ObjectOutputStream os = new ObjectOutputStream(bs)) { - os.writeObject(ma); + if (_main_panel.getMaster_pass() != null) { + + DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true); + + } else { + + DBTools.insertMegaSession(email, bs.toByteArray(), false); + } + + _main_panel.getMega_active_accounts().put(email, ma); + + password = pass; + + String password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash(); + + if (_main_panel.getMaster_pass() != null) { + + password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + + password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + + user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); + } + + DBTools.insertMegaAccount(email, password, password_aes, user_hash); } - - if (_main_panel.getMaster_pass() != null) { - - DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true); - - } else { - - DBTools.insertMegaSession(email, bs.toByteArray(), false); - } - - _main_panel.getMega_active_accounts().put(email, ma); - - password = pass; - - String password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash(); - - if (_main_panel.getMaster_pass() != null) { - - password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - - password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - - user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV)); - } - - DBTools.insertMegaAccount(email, password, password_aes, user_hash); } else { email_error.add(email); } diff --git a/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java b/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java new file mode 100644 index 000000000..8595636ff --- /dev/null +++ b/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java @@ -0,0 +1,289 @@ +package com.tonikelope.megabasterd; + +import com.xuggle.xuggler.Global; +import com.xuggle.xuggler.ICodec; +import com.xuggle.xuggler.IContainer; +import com.xuggle.xuggler.IPacket; +import com.xuggle.xuggler.IPixelFormat; +import com.xuggle.xuggler.IStream; +import com.xuggle.xuggler.IStreamCoder; +import com.xuggle.xuggler.IVideoPicture; +import com.xuggle.xuggler.IVideoResampler; +import com.xuggle.xuggler.Utils; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +public class Thumbnailer { + + public Thumbnailer() { + } + + public static final int IMAGE_THUMB_SIZE = 250; + + /** + * The number of seconds between frames. + */ + public static final double SECONDS_BETWEEN_FRAMES = 10; + + /** + * The number of nano-seconds between frames. + */ + public static final long NANO_SECONDS_BETWEEN_FRAMES + = (long) (Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES); + + /** + * Time of last frame write. + */ + private long mLastPtsWrite = Global.NO_PTS; + + private int conta_frames = 0; + + /** + * Write the video frame out to a PNG file every once and a while. The files + * are written out to the system's temporary directory. + * + * @param picture the video frame which contains the time stamp. + * @param image the buffered image to write out + */ + private String processFrame(IVideoPicture picture, BufferedImage image) { + try { + // if uninitialized, backdate mLastPtsWrite so we get the very + // first frame + + if (mLastPtsWrite == Global.NO_PTS) { + mLastPtsWrite = picture.getPts() - NANO_SECONDS_BETWEEN_FRAMES; + } + + // if it's time to write the next frame + if (picture.getPts() - mLastPtsWrite >= NANO_SECONDS_BETWEEN_FRAMES) { + // Make a temorary file name + + if (conta_frames == 1) { + + File file = File.createTempFile("megabasterd_thumbnail_" + MiscTools.genID(20), ".jpg"); + + // write out JPG + ImageIO.write(image, "jpg", file); + + // indicate file written + //double seconds = ((double) picture.getPts()) / Global.DEFAULT_PTS_PER_SECOND; + //System.out.printf("at elapsed time of %6.3f seconds wrote: %s\n", seconds, file); + conta_frames++; + + return file.getAbsolutePath(); + } + + conta_frames++; + + // update last write time + mLastPtsWrite += NANO_SECONDS_BETWEEN_FRAMES; + + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + public String createImageThumbnail(String filename) { + try { + + BufferedImage imagen_original = ImageIO.read(new File(filename)); + + if (imagen_original.getHeight() <= IMAGE_THUMB_SIZE) { + return filename; + } + + int h = IMAGE_THUMB_SIZE; + + int w = Math.round((((float) imagen_original.getWidth()) * h) / imagen_original.getHeight()); + + BufferedImage newImage = new BufferedImage(w, h, imagen_original.getType()); + + Graphics2D g = newImage.createGraphics(); + + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + + g.drawImage(imagen_original, 0, 0, w, h, null); + + g.dispose(); + + File file = File.createTempFile("megabasterd_thumbnail_" + MiscTools.genID(20), ".png"); + + ImageIO.write(newImage, "png", file); + + return file.getAbsolutePath(); + + } catch (IOException ex) { + Logger.getLogger(Thumbnailer.class.getName()).log(Level.SEVERE, null, ex); + } + + return null; + } + + /** + * Takes a media container (file) as the first argument, opens it, reads + * through the file and captures video frames periodically as specified by + * SECONDS_BETWEEN_FRAMES. The frames are written as PNG files into the + * system's temporary directory. + * + * @param args must contain one string which represents a filename + */ + @SuppressWarnings("deprecation") + public String createVideoThumbnail(String filename) { + + // make sure that we can actually convert video pixel formats + if (!IVideoResampler.isSupported( + IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION)) { + throw new RuntimeException( + "you must install the GPL version of Xuggler (with IVideoResampler" + + " support) for this demo to work"); + } + + // create a Xuggler container object + IContainer container = IContainer.make(); + + // open up the container + if (container.open(filename, IContainer.Type.READ, null) < 0) { + throw new IllegalArgumentException("could not open file: " + filename); + } + + // query how many streams the call to open found + int numStreams = container.getNumStreams(); + + // and iterate through the streams to find the first video stream + int videoStreamId = -1; + IStreamCoder videoCoder = null; + for (int i = 0; i < numStreams; i++) { + // find the stream object + + IStream stream = container.getStream(i); + + // get the pre-configured decoder that can decode this stream; + IStreamCoder coder = stream.getStreamCoder(); + + if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { + videoStreamId = i; + videoCoder = coder; + break; + } + } + + if (videoStreamId == -1) { + throw new RuntimeException("could not find video stream in container: " + filename); + } + + // Now we have found the video stream in this file. Let's open up + // our decoder so it can do work + if (videoCoder.open() < 0) { + throw new RuntimeException( + "could not open video decoder for container: " + filename); + } + + IVideoResampler resampler = null; + if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) { + // if this stream is not in BGR24, we're going to need to + // convert it. The VideoResampler does that for us. + + resampler = IVideoResampler.make( + videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24, + videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType()); + if (resampler == null) { + throw new RuntimeException( + "could not create color space resampler for: " + filename); + } + } + + // Now, we start walking through the container looking at each packet. + IPacket packet = IPacket.make(); + + String frame_file = null; + + while (container.readNextPacket(packet) >= 0 && conta_frames < 2) { + + // Now we have a packet, let's see if it belongs to our video strea + if (packet.getStreamIndex() == videoStreamId) { + // We allocate a new picture to get the data out of Xuggle + + IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(), + videoCoder.getWidth(), videoCoder.getHeight()); + + int offset = 0; + + while (offset < packet.getSize()) { + // Now, we decode the video, checking for any errors. + + int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset); + if (bytesDecoded < 0) { + throw new RuntimeException("got error decoding video in: " + filename); + } + offset += bytesDecoded; + + // Some decoders will consume data in a packet, but will not + // be able to construct a full video picture yet. Therefore + // you should always check if you got a complete picture from + // the decode. + if (picture.isComplete()) { + IVideoPicture newPic = picture; + + // If the resampler is not null, it means we didn't get the + // video in BGR24 format and need to convert it into BGR24 + // format. + if (resampler != null) { + // we must resample + newPic = IVideoPicture.make( + resampler.getOutputPixelFormat(), picture.getWidth(), + picture.getHeight()); + if (resampler.resample(newPic, picture) < 0) { + throw new RuntimeException( + "could not resample video from: " + filename); + } + } + + if (newPic.getPixelType() != IPixelFormat.Type.BGR24) { + throw new RuntimeException( + "could not decode video as BGR 24 bit data in: " + filename); + } + + // convert the BGR24 to an Java buffered image + BufferedImage javaImage = Utils.videoPictureToImage(newPic); + + // process the video frame + frame_file = processFrame(newPic, javaImage); + + } + + } + } else { + // This packet isn't part of our video stream, so we just + // silently drop it. + do { + } while (false); + } + + } + + // Technically since we're exiting anyway, these will be cleaned up + // by the garbage collector... but because we're nice people and + // want to be invited places for Christmas, we're going to show how + // to clean up. + if (videoCoder != null) { + videoCoder.close(); + videoCoder = null; + } + if (container != null) { + container.close(); + container = null; + } + + return frame_file; + } +} diff --git a/src/main/java/com/tonikelope/megabasterd/Upload.java b/src/main/java/com/tonikelope/megabasterd/Upload.java index 4e87c5062..146551caf 100644 --- a/src/main/java/com/tonikelope/megabasterd/Upload.java +++ b/src/main/java/com/tonikelope/megabasterd/Upload.java @@ -16,6 +16,8 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import static java.lang.Integer.MAX_VALUE; +import java.nio.file.Files; +import java.nio.file.Paths; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -929,40 +931,79 @@ public class Upload implements Transference, Runnable, SecureSingleThreadNotifia } while (upload_res == null && !_exit); if (upload_res != null && !_exit) { - List files = (List) upload_res.get("f"); - - _fid = (String) ((Map) files.get(0)).get("h"); - try { + List files = (List) upload_res.get("f"); - _file_link = _ma.getPublicFileLink(_fid, i32a2bin(node_key)); + _fid = (String) ((Map) files.get(0)).get("h"); - MiscTools.GUIRun(() -> { - getView().getFile_link_button().setEnabled(true); - }); + if (MiscTools.isVideoFile(Paths.get(_file_name))) { - } catch (Exception ex) { - LOG.log(Level.SEVERE, ex.getMessage()); - } + getView().printStatusNormal("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***"); - getView().printStatusOK(LabelTranslatorSingleton.getInstance().translate("File successfully uploaded! (") + _ma.getFull_email() + ")"); + Thumbnailer thumbnailer = new Thumbnailer(); - synchronized (this.getMain_panel().getUpload_manager().getLog_file_lock()) { + String thumb_file = thumbnailer.createVideoThumbnail(_file_name); - File upload_log = new File(MainPanel.MEGABASTERD_HOME_DIR + "/megabasterd_upload_" + _root_node + ".log"); + if (thumb_file != null) { - if (upload_log.exists()) { + _ma.uploadThumbnails(this, _fid, thumb_file, thumb_file); - FileWriter fr; - try { - fr = new FileWriter(upload_log, true); - fr.write("[" + MiscTools.getFechaHoraActual() + "] " + _file_name + " [" + MiscTools.formatBytes(_file_size) + "] " + _file_link + "\n"); - fr.close(); - } catch (IOException ex) { - Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, ex.getMessage()); + Files.deleteIfExists(Paths.get(thumb_file)); + } + + } else if (MiscTools.isImageFile(Paths.get(_file_name))) { + + getView().printStatusNormal("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***"); + + Thumbnailer thumbnailer = new Thumbnailer(); + + String thumb_file = thumbnailer.createImageThumbnail(_file_name); + + if (thumb_file != null) { + + _ma.uploadThumbnails(this, _fid, thumb_file, thumb_file); + + Files.deleteIfExists(Paths.get(thumb_file)); } } + + try { + + _file_link = _ma.getPublicFileLink(_fid, i32a2bin(node_key)); + + MiscTools.GUIRun(() -> { + getView().getFile_link_button().setEnabled(true); + }); + + } catch (Exception ex) { + LOG.log(Level.SEVERE, ex.getMessage()); + } + + getView().printStatusOK(LabelTranslatorSingleton.getInstance().translate("File successfully uploaded! (") + _ma.getFull_email() + ")"); + + synchronized (this.getMain_panel().getUpload_manager().getLog_file_lock()) { + + File upload_log = new File(MainPanel.MEGABASTERD_HOME_DIR + "/megabasterd_upload_" + _root_node + ".log"); + + if (upload_log.exists()) { + + FileWriter fr; + try { + fr = new FileWriter(upload_log, true); + fr.write("[" + MiscTools.getFechaHoraActual() + "] " + _file_name + " [" + MiscTools.formatBytes(_file_size) + "] " + _file_link + "\n"); + fr.close(); + } catch (IOException ex) { + Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, ex.getMessage()); + } + + } + } + + } catch (MegaAPIException ex) { + Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex); } } else if (_status_error != null) { diff --git a/src/main/resources/images/mbasterd_screen.png b/src/main/resources/images/mbasterd_screen.png index 243991d96..dd5809362 100644 Binary files a/src/main/resources/images/mbasterd_screen.png and b/src/main/resources/images/mbasterd_screen.png differ