package com.ijoomer.components.jomsocial; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.media.MediaMetadataRetriever; import android.media.MediaPlayer; import android.net.Uri; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.VideoView; import com.coremedia.iso.IsoFile; import com.coremedia.iso.boxes.TimeToSampleBox; import com.googlecode.mp4parser.authoring.Movie; import com.googlecode.mp4parser.authoring.Track; import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder; import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator; import com.googlecode.mp4parser.authoring.tracks.CroppedTrack; import com.ijoomer.common.classes.IjoomerUtilities; import com.ijoomer.common.classes.VideoTrimmerUtilities; import com.ijoomer.common.configuration.IjoomerGlobalConfiguration; import com.ijoomer.custom.interfaces.CustomSliderListener; import com.ijoomer.customviews.CustomSliderView; import com.ijoomer.customviews.IjoomerButton; import com.ijoomer.customviews.IjoomerTextView; import com.ijoomer.library.jomsocial.JomGalleryDataProvider; import com.ijoomer.src.R; import com.ijoomer.weservice.WebCallListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; /** * This Class Contains All Method Related To JomVideoTrimmerActivity. * * @author tasol * */ @SuppressLint("NewApi") public class JomVideoTrimmerActivity extends JomMasterActivity implements OnTouchListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener ,CustomSliderListener{ private IjoomerButton btnTrimVideo; private IjoomerButton btnPlayVideo; private IjoomerTextView txtVideoTitleValue; private IjoomerTextView txtVideoDescriptionValue; private IjoomerTextView txtVideoLocationValue; private IjoomerTextView txtVideoDescription; private IjoomerTextView txtVideoStartTimeValue; private IjoomerTextView txtVideoEndTimeValue; private ImageView thumbBar; private ProgressBar pbrLoadVideoFrames; private ProgressBar pbrUploadVideo; private VideoView vvSlider; private CustomSliderView customSlider; public static ArrayList<Bitmap> bArrayForFrames; public static ArrayList<Bitmap> allTrackArray; private JomGalleryDataProvider providerAllVideos; private Context context; public static String IN_VIDEO_PATH_FOR_TRIMMING; public String IN_VIDEO_FILE; public String IN_VIDEO_TITLE; public String IN_VIDEO_DESCRIPTION; public String IN_VIDEO_CAPTION; public String IN_CAT_ID; public String IN_GROUP_ID; public String IN_PRIVACY; public String IN_LOCATION; private double extractMin; private double extractMax; private double extractMaxForTrimming; private double extractMinForTrimming; public double IN_LATITUDE; public double IN_LONGITUDE; private int endingTimeForPlayingVideo; private int startingTimeForPlayingVideo; private double calculatedWidth; private Timer timer; private int durationOfPlayingVideo ; /** * Overrides methods */ @Override public int setLayoutId() { return R.layout.jom_video_trim; } @Override public void initComponents() { btnTrimVideo = (IjoomerButton) findViewById(R.id.btnTrimVideo); btnPlayVideo = (IjoomerButton) findViewById(R.id.btnPlayVideo); txtVideoTitleValue = (IjoomerTextView) findViewById(R.id.txtVideoTitleValue); txtVideoDescription = (IjoomerTextView) findViewById(R.id.txtVideoDescription); txtVideoStartTimeValue = (IjoomerTextView) findViewById(R.id.txtVideoStartTimeValue); txtVideoEndTimeValue = (IjoomerTextView) findViewById(R.id.txtVideoEndTimeValue); txtVideoDescriptionValue = (IjoomerTextView) findViewById(R.id.txtVideoDescriptionValue); txtVideoLocationValue = (IjoomerTextView) findViewById(R.id.txtVideoLocationValue); thumbBar = (ImageView) findViewById(R.id.thumbBar); thumbBar.getLayoutParams().width = width; pbrLoadVideoFrames = (ProgressBar) findViewById(R.id.pbrLoadVideoFrames); pbrUploadVideo = (ProgressBar) findViewById(R.id.pbrUploadVideo); customSlider = (CustomSliderView) this.findViewById(R.id.customSlider); vvSlider = (VideoView) findViewById(R.id.vvSlider); vvSlider.setOnErrorListener(this); pbrLoadVideoFrames.setVisibility(View.VISIBLE); pbrUploadVideo.setVisibility(View.GONE); providerAllVideos = new JomGalleryDataProvider(this); } @Override public void prepareViews() { context = this; extractMinForTrimming = 0; getIntentData(); } @Override protected void onResume() { super.onResume(); vvSlider.setVideoURI(Uri.parse(IN_VIDEO_PATH_FOR_TRIMMING)); vvSlider.requestFocus(); vvSlider.setOnPreparedListener(this); vvSlider.setMediaController(null); } private void timerMethod() { this.runOnUiThread(generate); } private Runnable generate= new Runnable() { @SuppressWarnings("deprecation") @Override public void run() { if (vvSlider.isPlaying()) { /*System.out.println(":::vvSlider.getCurrentPosition() :::::"+vvSlider.getCurrentPosition()); System.out.println("extractMaxForTrimming :::::::"+(int) (VideoTrimmerUtilities.progressToTimer(durationOfPlayingVideo * 1000, extractMax))); if(vvSlider.getCurrentPosition()>((int) (VideoTrimmerUtilities.progressToTimer(durationOfPlayingVideo * 1000, extractMax)))){*/ vvSlider.pause(); btnPlayVideo.setBackgroundDrawable(getResources().getDrawable(R.drawable.jom_video_play_btn)); // } timer.cancel(); }else{ } } }; @Override public void setActionListeners() { btnPlayVideo.setOnClickListener(new OnClickListener() { @SuppressWarnings("deprecation") @Override public void onClick(View v) { if (vvSlider.isPlaying()) { vvSlider.pause(); btnPlayVideo.setBackgroundDrawable(getResources().getDrawable(R.drawable.jom_video_play_btn)); } else { timer = new Timer(); vvSlider.seekTo((int) (VideoTrimmerUtilities.progressToTimer(startingTimeForPlayingVideo * 1000, extractMax))); vvSlider.start(); btnPlayVideo.setBackgroundDrawable(getResources().getDrawable(R.drawable.jom_video_pause_btn)); if(extractMaxForTrimming<extractMinForTrimming){ durationOfPlayingVideo =(int) (extractMinForTrimming - extractMaxForTrimming); }else{ durationOfPlayingVideo = (int) (extractMaxForTrimming - extractMinForTrimming); } if(durationOfPlayingVideo <= 0){ durationOfPlayingVideo = 10; } if(durationOfPlayingVideo * 1000 < 0){ durationOfPlayingVideo = Math.abs(durationOfPlayingVideo); } timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { timerMethod(); } },durationOfPlayingVideo * 1000,durationOfPlayingVideo); } } }); btnTrimVideo.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setProgressBarVisibility(true); btnTrimVideo.setClickable(false); makeVideo(); } }); } @SuppressWarnings("deprecation") @Override public boolean onTouch(View view, MotionEvent event) { if (vvSlider.isPlaying()) { vvSlider.pause(); btnPlayVideo.setBackgroundDrawable(getResources().getDrawable(R.drawable.jom_video_play_btn)); } CustomSliderView customSliderView = (CustomSliderView) view; if (!customSliderView.getEvent() && (int) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax)) > 0 && (int) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax)) <= extractMax) { vvSlider.seekTo((int) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax))); double ms = calculateDurationFromWidth(); endingTimeForPlayingVideo = customSliderView.getScaledValue(); try { extractMaxForTrimming = VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue(), extractMax); double startTime = Double.valueOf(VideoTrimmerUtilities.milliSecondsToTimer((long) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax)))) < ms ? ms - Double.valueOf(VideoTrimmerUtilities.milliSecondsToTimer((long) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax)))) : Double.valueOf(VideoTrimmerUtilities.milliSecondsToTimer((long) (VideoTrimmerUtilities.progressToTimer( customSliderView.getScaledValue() * 1000, extractMax)))) - ms; double endTime = Double.valueOf(VideoTrimmerUtilities.milliSecondsToTimer((long) (VideoTrimmerUtilities.progressToTimer(customSliderView.getScaledValue() * 1000, extractMax)))); double startTimeConversion; double endTimeConversion; startTimeConversion = startTime; endTimeConversion = endTime; if(startTime > endTime){ endTime = startTimeConversion; startTime = endTimeConversion; } DecimalFormat f = new DecimalFormat("##0.00"); txtVideoStartTimeValue.setText(String.valueOf(f.format(startTime))); txtVideoEndTimeValue.setText(String.valueOf(endTime)); startingTimeForPlayingVideo = VideoTrimmerUtilities.getProgressPercentage((long) startTime, (long) endTime); extractMinForTrimming = VideoTrimmerUtilities.progressToTimer((int) startingTimeForPlayingVideo, extractMax); thumbBar.setPadding(width, 0, 0, 0); } catch (Throwable e) { } customSliderView.setCustomSliderListener(new CustomSliderListener() { @Override public int onThumbSizeChanged(int calculatedSizeOfThumb) { if(calculatedWidth<calculatedSizeOfThumb){ }else{ thumbBar.getLayoutParams().width = calculatedSizeOfThumb; customSlider.setResizedDistance((int) calculatedSizeOfThumb); } return 0; } }); } return true; } @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(true); extractMax = vvSlider.getDuration(); if (!customSlider.isShown()) { customSlider.setVisibility(View.VISIBLE); try { allTrackArray = new ArrayList<Bitmap>(); allTrackArray = getAllFrames(); customSlider.setTracks(allTrackArray); customSlider.setResourceIds(R.drawable.jom_custom_slider_thumb, R.drawable.jom_custom_slider_bar); customSlider.setDelegateOnTouchListener(this); try { long fileLength = new File(IN_VIDEO_PATH_FOR_TRIMMING).length(); calculatedWidth = ((IjoomerGlobalConfiguration.getVideoUploadSize() * (width)) / (fileLength / (1024 * 1024))); thumbBar.getLayoutParams().width = (int) calculatedWidth; customSlider.setDistance((int) calculatedWidth); double minTime = calculateDurationFromWidth(); double maxTime = Double.valueOf(VideoTrimmerUtilities.milliSecondsToTimer((long) extractMax)); System.out.println("::: MIN TIME ::::::"+minTime +":::maxTime ::::"+maxTime); DecimalFormat f = new DecimalFormat("##0.00"); txtVideoEndTimeValue.setText(String.valueOf(f.format(minTime))); txtVideoStartTimeValue.setText(String.valueOf(extractMinForTrimming)); endingTimeForPlayingVideo = VideoTrimmerUtilities.getProgressPercentage((long) minTime, (long) maxTime); extractMaxForTrimming = VideoTrimmerUtilities.progressToTimer((int) endingTimeForPlayingVideo, extractMax); customSlider.setRange(1, 100); customSlider.setScaledValue(1); } catch (Throwable e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } } @Override public boolean onError(MediaPlayer mp, int what, int extra) { ting(context.getString(R.string.error_loading_video)); return false; } /** * Class methods */ /** * This method used to get intent data. */ public void getIntentData() { IN_VIDEO_PATH_FOR_TRIMMING = getIntent().getExtras().getString("IN_VIDEO_PATH_FOR_TRIMMING"); IN_GROUP_ID = getIntent().getStringExtra("IN_GROUP_ID") == null ? "0" : getIntent().getStringExtra("IN_GROUP_ID"); IN_VIDEO_FILE = getIntent().getStringExtra("IN_VIDEO_FILE") == null ? "0" : getIntent().getStringExtra("IN_VIDEO_FILE"); IN_VIDEO_TITLE = getIntent().getStringExtra("IN_VIDEO_TITLE") == null ? "0" : getIntent().getStringExtra("IN_VIDEO_TITLE"); IN_VIDEO_DESCRIPTION = getIntent().getStringExtra("IN_VIDEO_DESCRIPTION") == null ? "0" : getIntent().getStringExtra("IN_VIDEO_DESCRIPTION"); IN_VIDEO_CAPTION = getIntent().getStringExtra("IN_VIDEO_CAPTION") == null ? "0" : getIntent().getStringExtra("IN_VIDEO_CAPTION"); IN_LATITUDE = Double.valueOf(getIntent().getStringExtra("IN_LATITUDE") == null ? "0" : getIntent().getStringExtra("IN_LATITUDE")); IN_LONGITUDE = Double.valueOf(getIntent().getStringExtra("IN_LONGITUDE") == null ? "0" : getIntent().getStringExtra("IN_LONGITUDE")); IN_CAT_ID = getIntent().getStringExtra("IN_CAT_ID") == null ? "0" : getIntent().getStringExtra("IN_CAT_ID"); IN_PRIVACY = getIntent().getStringExtra("IN_PRIVACY") == null ? "0" : getIntent().getStringExtra("IN_PRIVACY"); IN_LOCATION = getIntent().getStringExtra("IN_LOCATION") == null ? "0" : getIntent().getStringExtra("IN_LOCATION"); if(IN_VIDEO_DESCRIPTION!=null){ txtVideoDescription.setVisibility(View.VISIBLE); } txtVideoDescriptionValue.setText(": " +IN_VIDEO_DESCRIPTION); txtVideoTitleValue.setText(": " +IN_VIDEO_TITLE); txtVideoLocationValue.setText(": " +IN_LOCATION); } /** * This method used to make custom video. */ @SuppressWarnings("resource") public void makeVideo() { Movie movie; try { movie = MovieCreator.build(new FileInputStream(IN_VIDEO_PATH_FOR_TRIMMING).getChannel()); List<Track> tracks = movie.getTracks(); movie.setTracks(new LinkedList<Track>()); double startTime = extractMinForTrimming; double endTime = extractMaxForTrimming; if(extractMinForTrimming > extractMaxForTrimming){ startTime = extractMaxForTrimming; endTime = extractMinForTrimming; } boolean timeCorrected = false; for (Track track : tracks) { if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { if (timeCorrected) { throw new RuntimeException(context.getString(R.string.error_same_track)); } startTime = correctTimeToSyncSample(track, startTime, false); endTime = correctTimeToSyncSample(track, endTime, true); timeCorrected = true; } } for (Track track : tracks) { long currentSample = 0; double currentTime = 0; long startSample = -1; long endSample = -1; for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); for (int j = 0; j < entry.getCount(); j++) { if (currentTime <= startTime) { startSample = currentSample; } if (currentTime <= endTime) { endSample = currentSample; } else { break; } currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale(); currentSample++; } } movie.addTrack(new CroppedTrack(track, startSample, endSample)); } IsoFile out = new DefaultMp4Builder().build(movie); FileOutputStream fos; try { fos = new FileOutputStream(String.format(context.getString(R.string.path_of_trimmed_video), startTime, endTime)); FileChannel fc = fos.getChannel(); out.getBox(fc); fos.close(); } catch (Exception e) { e.printStackTrace(); } try { IN_VIDEO_FILE = context.getString(R.string.path_of_sd_card) + context.getString(R.string.path_of_trimmed_video); double fileLength = new File(context.getString(R.string.path_of_trimmed_video)).length(); double bytesCalculation = fileLength / (1024 * 1024); if (bytesCalculation > IjoomerGlobalConfiguration.getVideoUploadSize()) { extractMinForTrimming = extractMinForTrimming + 50; makeVideo(); } else { btnTrimVideo.setClickable(true); startVideoUpload(IN_GROUP_ID, IN_VIDEO_FILE, IN_VIDEO_TITLE, IN_VIDEO_DESCRIPTION, IN_VIDEO_CAPTION, IN_LATITUDE, IN_LONGITUDE, IN_CAT_ID, IN_PRIVACY); } } catch (Throwable e) { e.printStackTrace(); } } catch (Exception e1) { e1.printStackTrace(); } } /** * This method used to get video duration. * @param track represented track * @return represented {@link Long} */ protected static long getDuration(Track track) { long duration = 0; for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) { duration += entry.getCount() * entry.getDelta(); } return duration; } /** * This method used to correct time to sync sample. * @param track represented track * @param cutHere represented cut * @param next represented is next * @return represented {@link Double} */ private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) { double[] timeOfSyncSamples = new double[track.getSyncSamples().length]; long currentSample = 0; double currentTime = 0; for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); for (int j = 0; j < entry.getCount(); j++) { if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) { timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime; } currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale(); currentSample++; } } double previous = 0; for (double timeOfSyncSample : timeOfSyncSamples) { if (timeOfSyncSample > cutHere) { if (next) { return timeOfSyncSample; } else { return previous; } } previous = timeOfSyncSample; } return timeOfSyncSamples[timeOfSyncSamples.length - 1]; } /** * This method used to get all frames from video. * @return represented {@link Bitmap} list */ @SuppressLint({ "NewApi", "NewApi" }) public ArrayList<Bitmap> getAllFrames() { bArrayForFrames = new ArrayList<Bitmap>(); bArrayForFrames.clear(); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(IN_VIDEO_PATH_FOR_TRIMMING); for (int i = (int) extractMin; i < (int) extractMax; i++) { if (bArrayForFrames != null && bArrayForFrames.size() > 20 && bArrayForFrames.size() != i) { break; } else { if (bArrayForFrames.size() == 19) { bArrayForFrames.add(retriever.getFrameAtTime((long) extractMax * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); } else { if (i % 5000 == 0) { bArrayForFrames.add(retriever.getFrameAtTime((long) extractMin * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); } } } extractMin = i + 4999; } } catch (IllegalArgumentException ex) { ex.printStackTrace(); } catch (RuntimeException ex) { ex.printStackTrace(); } finally { try { retriever.release(); } catch (RuntimeException ex) { } } pbrLoadVideoFrames.setVisibility(View.GONE); btnPlayVideo.setVisibility(View.VISIBLE); return bArrayForFrames; } /** * This method used to calculate duration from width. * @return */ public double calculateDurationFromWidth() { double ms = 0; ms = (thumbBar.getLayoutParams().width / extractMax); return ms * 10000; } /** * This method used to start upload video * @param groupID represented group id * @param videoFilePath represented video file path * @param videoTitle represented video title * @param description represented video description * @param videoCaption represented video caption * @param lat represented latitude * @param lng represented longitude * @param categoryID represented category id * @param privacy represented privacy */ private void startVideoUpload(final String groupID, final String videoFilePath, final String videoTitle, final String description, final String videoCaption, final double lat, final double lng, final String categoryID, final String privacy) { this.finish(); IjoomerUtilities.addToNotificationBar(getString(R.string.video_upload_starts), getString(R.string.uplod_video), getString(R.string.video_upload_starts)); providerAllVideos.uploadVideo(groupID, videoFilePath, videoTitle, description, videoCaption, lat, lng, categoryID, privacy, new WebCallListener() { @Override public void onProgressUpdate(int progressCount) { } @Override public void onCallComplete(int responseCode, String errorMessage, ArrayList<HashMap<String, String>> data1, Object data2) { if (responseCode == 200) { IjoomerUtilities.addToNotificationBar(getString(R.string.video_upload_successfully), getString(R.string.uplod_video), getString(R.string.video_upload_successfully)); } else { if (errorMessage != null && errorMessage.length() > 0) { IjoomerUtilities.addToNotificationBar(getString(R.string.video_upload_failure), getString(R.string.uplod_video), errorMessage); } else { IjoomerUtilities.addToNotificationBar(getString(R.string.video_upload_failure), getString(R.string.uplod_video), getString(getResources().getIdentifier("code" + responseCode, "string", getPackageName()))); } } } }); } @Override public int onThumbSizeChanged(int calculatedSizeOfThumb) { System.out.println(":::calculatedSizeOfThumb ::::::"+calculatedSizeOfThumb); return 0; } }