title: MediaMuxer video file size reducing (re-compress, decrease resolution)
body: <p>I'm looking for efficient way to reduce some video weight (as a <code>File</code>, for upload) and obvious answer for that is: lets reduce resolution! (fullHD or 4K not needed, simple HD is sufficient for me) I've tried lot of ways which should work through lot of APIs (needed 10) and best way was using <a href="https://github.com/guardianproject/android-ffmpeg-java" rel="noreferrer">android-ffmpeg-java</a>, BUT... on my pretty fast almost-current flagship device whole process lasts about length_of_video*4 seconds and also this lib weight is 9 Mb, this amount increases my app size... No wai! (12 Mb to 1 Mb is nice result, but still too many flaws)</p>
  
  <p>So I've decided to use native Android ways to do this, <code>MediaMuxer</code> and <code>MediaCodec</code> - they are available from API18 and API16 respectivelly (older devices users: sorry; but they also often have "lower-res" camera). Below method <em>almost</em> works - <code>MediaMuxer</code> do NOT respect <code>MediaFormat.KEY_WIDTH</code> and <code>MediaFormat.KEY_HEIGHT</code> - extracted <code>File</code> is "re-compressed", weight is a bit smaller, but resolution is the same as in original video <code>File</code>...</p>
  
  <p>So, question: How to compress and re-scale/change resolution of video using <code>MediaMuxer</code> and other accompanying classes and methods?</p>
  
  <pre><code>public File getCompressedFile(String videoPath) throws IOException{
      MediaExtractor extractor = new MediaExtractor();
      extractor.setDataSource(videoPath);
      int trackCount = extractor.getTrackCount();
  
      String filePath = videoPath.substring(0, videoPath.lastIndexOf(File.separator));
      String[] splitByDot = videoPath.split("\\.");
      String ext="";
      if(splitByDot!=null &amp;&amp; splitByDot.length&gt;1)
          ext = splitByDot[splitByDot.length-1];
      String fileName = videoPath.substring(videoPath.lastIndexOf(File.separator)+1,
                      videoPath.length());
      if(ext.length()&gt;0)
          fileName=fileName.replace("."+ext, "_out."+ext);
      else
          fileName=fileName.concat("_out");
  
      final File outFile = new File(filePath, fileName);
      if(!outFile.exists())
          outFile.createNewFile();
  
      MediaMuxer muxer = new MediaMuxer(outFile.getAbsolutePath(),
              MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
      HashMap&lt;Integer, Integer&gt; indexMap = new HashMap&lt;Integer, Integer&gt;(trackCount);
      for (int i = 0; i &lt; trackCount; i++) {
          extractor.selectTrack(i);
          MediaFormat format = extractor.getTrackFormat(i);
          String mime = format.getString(MediaFormat.KEY_MIME);
          if(mime!=null &amp;&amp; mime.startsWith("video")){
              int currWidth = format.getInteger(MediaFormat.KEY_WIDTH);
              int currHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
              format.setInteger(MediaFormat.KEY_WIDTH, currWidth&gt;currHeight ? 960 : 540);
              format.setInteger(MediaFormat.KEY_HEIGHT, currWidth&gt;currHeight ? 540 : 960);
              //API19 MediaFormat.KEY_MAX_WIDTH and KEY_MAX_HEIGHT
              format.setInteger("max-width", format.getInteger(MediaFormat.KEY_WIDTH));
              format.setInteger("max-height", format.getInteger(MediaFormat.KEY_HEIGHT));
          }
          int dstIndex = muxer.addTrack(format);
          indexMap.put(i, dstIndex);
      }
  
      boolean sawEOS = false;
      int bufferSize = 256 * 1024;
      int offset = 100;
      ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
      MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
      muxer.start();
      while (!sawEOS) {
          bufferInfo.offset = offset;
          bufferInfo.size = extractor.readSampleData(dstBuf, offset);
          if (bufferInfo.size &lt; 0) {
              sawEOS = true;
              bufferInfo.size = 0;
          } else {
              bufferInfo.presentationTimeUs = extractor.getSampleTime();
              bufferInfo.flags = extractor.getSampleFlags();
              int trackIndex = extractor.getSampleTrackIndex();
              muxer.writeSampleData(indexMap.get(trackIndex), dstBuf,
                      bufferInfo);
              extractor.advance();
          }
      }
  
      muxer.stop();
      muxer.release();
  
      return outFile;
  }
  </code></pre>
  
  <p>PS. lot of usefull stuff about muxer <a href="http://bigflake.com/mediacodec/" rel="noreferrer">here</a>, above code bases on <code>MediaMuxerTest.java</code>, method <code>cloneMediaUsingMuxer</code></p>