2017-10-31 7 views
0

비디오를 압축하려고합니다. 비디오가 가로 모드 인 경우 코드가 제대로 작동하지만 비디오가 세로 모드 인 경우 코드가 가로 방향으로 회전합니다. 내 코드 :비디오 문제를 회전하는 Telegram API를 사용한 비디오 압축

public File convertVideo(String path) { 
    MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 
    try { 
     FileInputStream inputStream = new FileInputStream(path); 

     retriever.setDataSource(path); 

    } 
    catch (Exception e){ 
     e.printStackTrace(); 
    } 


    String width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); 
    String height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); 
    String rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); 

    long startTime = -1; 
    long endTime = -1; 

    int resultWidth = 640; 
    int resultHeight = 360; 

    int maxPortWidth = 360; 
    int maxPortHeight = 640; 

    int maxLandWidth = 640; 
    int maxLandHeight = 360; 

    float imgRatio; 
    float maxRatio; 


    int rotationValue = Integer.valueOf(rotation); 
    int originalWidth = Integer.valueOf(width); 
    int originalHeight = Integer.valueOf(height); 


    int bitrate = 921600; 
    int rotateRender = 0; 

    File folder = new File(Environment.getExternalStorageDirectory() + File.separator 
      + Config.VIDEO_COMPRESSOR_APPLICATION_DIR_NAME); 
    boolean isDirExist = false; 
    if (!folder.exists()) { 
     isDirExist = folder.mkdir(); 
    } 
    isDirExist = false; 
    folder = new File(Environment.getExternalStorageDirectory() + File.separator 
      + Config.VIDEO_COMPRESSOR_APPLICATION_DIR_NAME+ Config.VIDEO_COMPRESSOR_COMPRESSED_VIDEOS_DIR); 
    if (!folder.exists()) { 
     isDirExist = folder.mkdir(); 
    } 

    File cacheFile = new File(
      Environment.getExternalStorageDirectory() 
        + File.separator 
        + Config.VIDEO_COMPRESSOR_APPLICATION_DIR_NAME 
        + Config.VIDEO_COMPRESSOR_COMPRESSED_VIDEOS_DIR, 
      "VIDEO_" + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()) + ".mp4" 
    ); 

    if(rotation.equals("90") || rotation.equals("270")) { 

     imgRatio = originalWidth/originalHeight; 
     maxRatio = maxPortWidth/maxPortHeight; 
     if (originalHeight > maxPortHeight || originalWidth > maxPortWidth) { 
      if (imgRatio < maxRatio) { 
       imgRatio = maxPortHeight/originalHeight; 
       resultWidth = (int) (imgRatio * originalWidth); 
       resultHeight = (int) maxPortHeight; 
      } else if (imgRatio > maxRatio) { 
       imgRatio = maxPortWidth/originalWidth; 
       resultHeight = (int) (imgRatio * originalHeight); 
       resultWidth = (int) maxPortWidth; 
      } else { 
       resultHeight = (int) maxPortHeight; 
       resultWidth = (int) maxPortWidth; 

      } 
     }   

    } else { 

     imgRatio = originalWidth/originalHeight; 
     maxRatio = maxLandWidth/maxLandHeight; 
     if (originalHeight > maxLandHeight || originalWidth > maxLandWidth) { 
      if (imgRatio!=0.0 && (imgRatio < maxRatio)) { 
       imgRatio = maxLandHeight/originalHeight; 
       resultWidth = (int) (imgRatio * originalWidth); 
       resultHeight = (int) maxLandHeight; 
      } else if (imgRatio!=0.0 && (imgRatio > maxRatio)) { 
       imgRatio = maxLandWidth/originalWidth; 
       resultHeight = (int) (imgRatio * originalHeight); 
       resultWidth = (int) maxLandWidth; 
      } else { 
       resultHeight = (int) maxLandHeight; 
       resultWidth = (int) maxLandWidth; 

      } 
     } 
    } 
    if (Build.VERSION.SDK_INT < 18 && resultHeight > resultWidth && resultWidth != originalWidth && resultHeight != originalHeight) { 
     int temp = resultHeight; 
     resultHeight = resultWidth; 
     resultWidth = temp; 
     rotationValue = 90; 
     rotateRender = 270; 
    } else if (Build.VERSION.SDK_INT > 20) { 
     if(rotationValue == 0) { 

      rotateRender = 0; 
     } else if (rotationValue == 90) { 
      int temp = resultHeight; 
      resultHeight = resultWidth; 
      resultWidth = temp; 
      rotationValue = 0; 
      rotateRender = 270; 
     } else if (rotationValue == 180) { 
      rotateRender = 180; 
      rotationValue = 0; 
     } else if (rotationValue == 270) { 
      int temp = resultHeight; 
      resultHeight = resultWidth; 
      resultWidth = temp; 
      rotationValue = 0; 
      rotateRender = 90; 
     } 
    } 
    File inputFile = new File(path); 
    if (!inputFile.canRead()) { 
     didWriteData(true, true); 
     return null; 
    } else { 
    } 

    videoConvertFirstWrite = true; 
    boolean error = false; 
    long videoStartTime = startTime; 
    long time = System.currentTimeMillis(); 
    if (resultWidth != 0 && resultHeight != 0) { 
     MP4Builder mediaMuxer = null; 
     MediaExtractor extractor = null; 

     try { 
      MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 
      Mp4Movie movie = new Mp4Movie(); 
      movie.setCacheFile(cacheFile); 
      movie.setRotation(rotationValue); 
      movie.setSize(resultWidth, resultHeight); 
      mediaMuxer = new MP4Builder().createMovie(movie); 
      extractor = new MediaExtractor(); 
      extractor.setDataSource(inputFile.toString()); 


      if (resultWidth != originalWidth || resultHeight != originalHeight) { 
       int videoIndex; 
       videoIndex = selectTrack(extractor, false); 

       if (videoIndex >= 0) { 
        MediaCodec decoder = null; 
        MediaCodec encoder = null; 
        InputSurface inputSurface = null; 
        OutputSurface outputSurface = null; 
        try { 
         long videoTime = -1; 
         boolean outputDone = false; 
         boolean inputDone = false; 
         boolean decoderDone = false; 
         int swapUV = 0; 
         int videoTrackIndex = -5; 

         int colorFormat; 
         int processorType = PROCESSOR_TYPE_OTHER; 
         String manufacturer = Build.MANUFACTURER.toLowerCase(); 
         if (Build.VERSION.SDK_INT < 18) { 
          MediaCodecInfo codecInfo = selectCodec(MIME_TYPE); 
          colorFormat = selectColorFormat(codecInfo, MIME_TYPE); 
          if (colorFormat == 0) { 
           throw new RuntimeException("no supported color format"); 
          } 
          String codecName = codecInfo.getName(); 
          if (codecName.contains("OMX.qcom.")) { 
           processorType = PROCESSOR_TYPE_QCOM; 
           if (Build.VERSION.SDK_INT == 16) { 
            if (manufacturer.equals("lge") || manufacturer.equals("nokia")) { 
             swapUV = 1; 
            } 
           } 
          } else if (codecName.contains("OMX.Intel.")) { 
           processorType = PROCESSOR_TYPE_INTEL; 
          } else if (codecName.equals("OMX.MTK.VIDEO.ENCODER.AVC")) { 
           processorType = PROCESSOR_TYPE_MTK; 
          } else if (codecName.equals("OMX.SEC.AVC.Encoder")) { 
           processorType = PROCESSOR_TYPE_SEC; 
           swapUV = 1; 
          } else if (codecName.equals("OMX.TI.DUCATI1.VIDEO.H264E")) { 
           processorType = PROCESSOR_TYPE_TI; 
          } 
          Log.e("tmessages", "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer + "device = " + Build.MODEL); 
         } else { 
          colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface; 
         } 


         int resultHeightAligned = resultHeight; 
         int padding = 0; 
         int bufferSize = resultWidth * resultHeight * 3/2; 
         if (processorType == PROCESSOR_TYPE_OTHER) { 
          if (resultHeight % 16 != 0) { 
           resultHeightAligned += (16 - (resultHeight % 16)); 
           padding = resultWidth * (resultHeightAligned - resultHeight); 
           bufferSize += padding * 5/4; 
          } 
         } else if (processorType == PROCESSOR_TYPE_QCOM) { 
          if (!manufacturer.toLowerCase().equals("lge")) { 
           int uvoffset = (resultWidth * resultHeight + 2047) & ~2047; 
           padding = uvoffset - (resultWidth * resultHeight); 
           bufferSize += padding; 
          } 
         } else if (processorType == PROCESSOR_TYPE_TI) { 

         } else if (processorType == PROCESSOR_TYPE_MTK) { 
          if (manufacturer.equals("baidu")) { 
           resultHeightAligned += (16 - (resultHeight % 16)); 
           padding = resultWidth * (resultHeightAligned - resultHeight); 
           bufferSize += padding * 5/4; 
          } 
         } 

         extractor.selectTrack(videoIndex); 
         if (startTime > 0) { 
          extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); 
         } else { 
          extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); 
         } 
         MediaFormat inputFormat = extractor.getTrackFormat(videoIndex); 

         MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight); 
         outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); 
         outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate != 0 ? bitrate : 921600); 
         outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25); 
         outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); 
         if (Build.VERSION.SDK_INT < 18) { 
          outputFormat.setInteger("stride", resultWidth + 32); 
          outputFormat.setInteger("slice-height", resultHeight); 
         } 

         encoder = MediaCodec.createEncoderByType(MIME_TYPE); 
         encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
         if (Build.VERSION.SDK_INT >= 18) { 
          inputSurface = new InputSurface(encoder.createInputSurface()); 
          inputSurface.makeCurrent(); 
         } 
         encoder.start(); 

         decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME)); 
         if (Build.VERSION.SDK_INT >= 18) { 
          outputSurface = new OutputSurface(); 
         } else { 
          outputSurface = new OutputSurface(resultWidth, resultHeight, rotateRender); 
         } 
         decoder.configure(inputFormat, outputSurface.getSurface(), null, 0); 
         decoder.start(); 

         final int TIMEOUT_USEC = 2500; 
         ByteBuffer[] decoderInputBuffers = null; 
         ByteBuffer[] encoderOutputBuffers = null; 
         ByteBuffer[] encoderInputBuffers = null; 
         if (Build.VERSION.SDK_INT < 21) { 
          decoderInputBuffers = decoder.getInputBuffers(); 
          encoderOutputBuffers = encoder.getOutputBuffers(); 
          if (Build.VERSION.SDK_INT < 18) { 
           encoderInputBuffers = encoder.getInputBuffers(); 
          } 
         } 

         while (!outputDone) { 
          if (!inputDone) { 
           boolean eof = false; 
           int index = extractor.getSampleTrackIndex(); 
           if (index == videoIndex) { 
            int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); 
            if (inputBufIndex >= 0) { 
             ByteBuffer inputBuf; 
             if (Build.VERSION.SDK_INT < 21) { 
              inputBuf = decoderInputBuffers[inputBufIndex]; 
             } else { 
              inputBuf = decoder.getInputBuffer(inputBufIndex); 
             } 
             int chunkSize = extractor.readSampleData(inputBuf, 0); 
             if (chunkSize < 0) { 
              decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
              inputDone = true; 
             } else { 
              decoder.queueInputBuffer(inputBufIndex, 0, chunkSize, extractor.getSampleTime(), 0); 
              extractor.advance(); 
             } 
            } 
           } else if (index == -1) { 
            eof = true; 
           } 
           if (eof) { 
            int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); 
            if (inputBufIndex >= 0) { 
             decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
             inputDone = true; 
            } 
           } 
          } 

          boolean decoderOutputAvailable = !decoderDone; 
          boolean encoderOutputAvailable = true; 
          while (decoderOutputAvailable || encoderOutputAvailable) { 
           int encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC); 
           if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { 
            encoderOutputAvailable = false; 
           } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 
            if (Build.VERSION.SDK_INT < 21) { 
             encoderOutputBuffers = encoder.getOutputBuffers(); 
            } 
           } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
            MediaFormat newFormat = encoder.getOutputFormat(); 
            if (videoTrackIndex == -5) { 
             videoTrackIndex = mediaMuxer.addTrack(newFormat, false); 
            } 
           } else if (encoderStatus < 0) { 
            throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus); 
           } else { 
            ByteBuffer encodedData; 
            if (Build.VERSION.SDK_INT < 21) { 
             encodedData = encoderOutputBuffers[encoderStatus]; 
            } else { 
             encodedData = encoder.getOutputBuffer(encoderStatus); 
            } 
            if (encodedData == null) { 
             throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null"); 
            } 
            if (info.size > 1) { 
             if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { 
              if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) { 
               didWriteData(false, false); 
              } 
             } else if (videoTrackIndex == -5) { 
              byte[] csd = new byte[info.size]; 
              encodedData.limit(info.offset + info.size); 
              encodedData.position(info.offset); 
              encodedData.get(csd); 
              ByteBuffer sps = null; 
              ByteBuffer pps = null; 
              for (int a = info.size - 1; a >= 0; a--) { 
               if (a > 3) { 
                if (csd[a] == 1 && csd[a - 1] == 0 && csd[a - 2] == 0 && csd[a - 3] == 0) { 
                 sps = ByteBuffer.allocate(a - 3); 
                 pps = ByteBuffer.allocate(info.size - (a - 3)); 
                 sps.put(csd, 0, a - 3).position(0); 
                 pps.put(csd, a - 3, info.size - (a - 3)).position(0); 
                 break; 
                } 
               } else { 
                break; 
               } 
              } 

              MediaFormat newFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight); 
              if (sps != null && pps != null) { 
               newFormat.setByteBuffer("csd-0", sps); 
               newFormat.setByteBuffer("csd-1", pps); 
              } 
              videoTrackIndex = mediaMuxer.addTrack(newFormat, false); 
             } 
            } 
            outputDone = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; 
            encoder.releaseOutputBuffer(encoderStatus, false); 
           } 
           if (encoderStatus != MediaCodec.INFO_TRY_AGAIN_LATER) { 
            continue; 
           } 

           if (!decoderDone) { 
            int decoderStatus = decoder.dequeueOutputBuffer(info, TIMEOUT_USEC); 
            if (decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { 
             decoderOutputAvailable = false; 
            } else if (decoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 

            } else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
             MediaFormat newFormat = decoder.getOutputFormat(); 

            } else if (decoderStatus < 0) { 
             throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus); 
            } else { 
             boolean doRender; 
             if (Build.VERSION.SDK_INT >= 18) { 
              doRender = info.size != 0; 
             } else { 
              doRender = info.size != 0 || info.presentationTimeUs != 0; 
             } 
             if (endTime > 0 && info.presentationTimeUs >= endTime) { 
              inputDone = true; 
              decoderDone = true; 
              doRender = false; 
              info.flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM; 
             } 
             if (startTime > 0 && videoTime == -1) { 
              if (info.presentationTimeUs < startTime) { 
               doRender = false; 

              } else { 
               videoTime = info.presentationTimeUs; 
              } 
             } 
             decoder.releaseOutputBuffer(decoderStatus, doRender); 
             if (doRender) { 
              boolean errorWait = false; 
              try { 
               outputSurface.awaitNewImage(); 
              } catch (Exception e) { 
               errorWait = true; 

              } 
              if (!errorWait) { 
               if (Build.VERSION.SDK_INT >= 18) { 
                outputSurface.drawImage(false); 
                inputSurface.setPresentationTime(info.presentationTimeUs * 1000); 
                inputSurface.swapBuffers(); 
               } else { 
                int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC); 
                if (inputBufIndex >= 0) { 
                 outputSurface.drawImage(true); 
                 ByteBuffer rgbBuf = outputSurface.getFrame(); 
                 ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex]; 
                 yuvBuf.clear(); 
                 convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV); 
                 encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0); 
                } else { 

                } 
               } 
              } 
             } 
             if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 
              decoderOutputAvailable = false; 

              if (Build.VERSION.SDK_INT >= 18) { 
               encoder.signalEndOfInputStream(); 
              } else { 
               int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC); 
               if (inputBufIndex >= 0) { 
                encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
               } 
              } 
             } 
            } 
           } 
          } 
         } 
         if (videoTime != -1) { 
          videoStartTime = videoTime; 
         } 
        } catch (Exception e) { 

         error = true; 
        } 

        extractor.unselectTrack(videoIndex); 

        if (outputSurface != null) { 
         outputSurface.release(); 
        } 
        if (inputSurface != null) { 
         inputSurface.release(); 
        } 
        if (decoder != null) { 
         decoder.stop(); 
         decoder.release(); 
        } 
        if (encoder != null) { 
         encoder.stop(); 
         encoder.release(); 
        } 
       } 
      } else { 
       long videoTime = readAndWriteTrack(extractor, mediaMuxer, info, startTime, endTime, cacheFile, false); 

       if (videoTime != -1) { 
        videoStartTime = videoTime; 
       } 
      } 
      if (!error) { 
       readAndWriteTrack(extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true); 
      } 
     } catch (Exception e) { 
      error = true; 

      e.printStackTrace(); 

     } finally { 
      if (extractor != null) { 
       extractor.release(); 
      } 
      if (mediaMuxer != null) { 
       try { 
        mediaMuxer.finishMovie(false); 
       } catch (Exception e) { 


       } 
      } 

     } 
    } else { 
     didWriteData(true, true); 
     return null; 
    } 
    didWriteData(true, error); 

    return cacheFile; 
} 

전보 앱 비디오 압축 https://github.com/lalongooo/VideoCompressor/blob/master/app/src/main/java/com/lalongooo/videocompressor/video/MediaController.java

답변

0

단순히 압축 함수를 호출하기 전에 조건을 넣어 해결했다. MediaMetaDataRetriever를 사용하여 선택한 비디오 높이와 너비를 확인하고 조건을 설정합니다. 1 : 1 비율 비디오의 경우 640x360으로 변환됩니다. 따라서 압축 전에 Width와 Height를 가져오고 압축 여부를 결정하십시오.

public void compress() { 

Log.w("VideoMessage","eNTERED : "+inputPath); 
lMediaMetadataRetriever.setDataSource(inputPath); 
String lVideoWidth = lMediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); 
Log.w("VideoMessage","VideoWidth: "+lVideoWidth); 
String lVideoHeight = lMediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); 
Log.w("VideoMessage","VideoHeight: "+lVideoHeight); 
if(Integer.valueOf(lVideoWidth)<=640 || Integer.valueOf(lVideoHeight)<=360){ 
    Toast.makeText(this, "Video Already in compressed form", Toast.LENGTH_SHORT).show(); 
} 
else{ 
    try2CreateCompressDir(); 
    outPath=Environment.getExternalStorageDirectory() 
      + File.separator 
      + APP_DIR 
      + COMPRESSED_VIDEOS_DIR 
      +"VIDEO_" + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()) + ".mp4"; 

    new VideoCompressor.execute(inputPath,outPath); 

} 

}

0

소스 비디오 변환 비디오 해상도가 같을 때 비디오를 회전하는 MediaController 구성 코드에 문제가 있습니다. 올바른 비디오 변환을 얻으려면 소스 비디오 너비/높이와 일치하지 않는 변환의 너비/높이를 지정해야합니다.