0

I have created a class to resize a video. I tested this with a video filmed on my mobile in portrait mode. The video is correctly displayed in portrait mode in any media player booth on phone and computer. However when using my program to resize the video is correctly resized but the rotation metadata is lost.

Querying the metadata of my input video via mediainfo gives the following output:

General
Complete name                            : /home/sneese/Downloads/20190708_095754.mp4
Format                                   : MPEG-4
Format profile                           : Base Media / Version 2
Codec ID                                 : mp42 (isom/mp42)
File size                                : 22.7 MiB
Duration                                 : 6s 741ms
Overall bit rate                         : 28.3 Mbps
Encoded date                             : UTC 2019-07-08 07:58:02
Tagged date                              : UTC 2019-07-08 07:58:02
com.android.version                      : 8.0.0

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L4.2
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 1 frame
Format settings, GOP                     : M=1, N=60
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 6s 732ms
Bit rate                                 : 28.0 Mbps
Width                                    : 1 920 pixels
Height                                   : 1 080 pixels
Display aspect ratio                     : 16:9
Rotation                                 : 90°
Frame rate mode                          : Variable
Frame rate                               : 60.000 fps
Minimum frame rate                       : 59.094 fps
Maximum frame rate                       : 60.934 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.225
Stream size                              : 22.5 MiB (99%)
Title                                    : VideoHandle
Language                                 : English
Encoded date                             : UTC 2019-07-08 07:58:02
Tagged date                              : UTC 2019-07-08 07:58:02
mdhd_Duration                            : 6732

Audio
ID                                       : 2
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : 40
Duration                                 : 6s 741ms
Source duration                          : 6s 745ms
Source_Duration_FirstFrame               : 3ms
Bit rate mode                            : Constant
Bit rate                                 : 256 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 48.0 KHz
Frame rate                               : 46.875 fps (1024 spf)
Compression mode                         : Lossy
Stream size                              : 211 KiB (1%)
Source stream size                       : 211 KiB (1%)
Title                                    : SoundHandle
Language                                 : English
Encoded date                             : UTC 2019-07-08 07:58:02
Tagged date                              : UTC 2019-07-08 07:58:02
mdhd_Duration                            : 6741

As you can see the rotation is set to 90 degrees.

This is my code:

Main Class: package test.video;

import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IMetaData;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;

public class MediaConverter {

      private static final String INPUT_FILE = "/home/user/input_video.mp4";
      private static final String OUTPUT_FILE = "/home/user/output_video.mp4";

      public static void main(String[] args) throws IOException {
          convertVideo(INPUT_FILE, OUTPUT_FILE, 640, 360);
      }

    private static void convertVideo(String inputFile, String outputFile, int width, int height){ 
            // reader
            IMediaReader reader = ToolFactory.makeReader(inputFile);
            Resizer resizer = new Resizer(width, height);
            reader.addListener(resizer);

            // writer
            IMediaWriter writer = ToolFactory.makeWriter(outputFile, reader);
            resizer.addListener(writer); 
            while (reader.readPacket() == null) { 
                // no need to do anything here just let him read
            }
        writer.flush();
    }
}

MediaToolAdapter: package test.video;

import com.xuggle.mediatool.MediaToolAdapter;
import com.xuggle.mediatool.event.IAddStreamEvent;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.mediatool.event.IWriteHeaderEvent;
import com.xuggle.mediatool.event.VideoPictureEvent;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IMetaData;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.IVideoResampler;
import java.util.Collection;

public class Resizer extends MediaToolAdapter {
      private Integer width;
      private Integer height;

      private IVideoResampler videoResampler = null;

      public Resizer(Integer aWidth, Integer aHeight) {
            this.width = aWidth;
            this.height = aHeight;
      }

      @Override
      public void onAddStream(IAddStreamEvent event) {
            int streamIndex = event.getStreamIndex();
            IStreamCoder streamCoder = event.getSource().getContainer().getStream(streamIndex).getStreamCoder();
            if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
            IStream stream = event.getSource().getContainer().getStream(streamIndex);
                  streamCoder.setWidth(width);
                  streamCoder.setHeight(height);
            // checked if this writes the metadata - but does not
            streamCoder.setProperty(stream.getMetaData(), null);
            event.getSource().getContainer().setMetaData(stream.getMetaData());
            }
            super.onAddStream(event);
      }

      @Override
      public void onVideoPicture(IVideoPictureEvent event) {
            IVideoPicture pic = event.getPicture();
            if (videoResampler == null) {
                videoResampler = IVideoResampler.make(width, height, pic.getPixelType(), pic.getWidth(), pic
                        .getHeight(), pic.getPixelType());
            }
            IVideoPicture out = IVideoPicture.make(pic.getPixelType(), width, height);
            videoResampler.resample(out, pic);

            IVideoPictureEvent asc = new VideoPictureEvent(event.getSource(), out, event.getStreamIndex());
            super.onVideoPicture(asc);
            out.delete();
      }
}

Expected result would be that the video is displayed in portrait mode after conversion if it was like that before the conversion otherwise landscape mode. Thank you

ulanBator
  • 45
  • 1
  • 6
  • "How to write rotation metadata to video in xuggler?": I dont know that - but portrait mode, isnt that 90 rotated?? Perhaps you mixed the eggs with the basket – gpasch Jul 10 '19 at 08:33
  • @gpasch What do you mean? It is 90 degrees rotated but the information for this is in the metadata. But it does not get written when converted so the info is lost. – ulanBator Jul 10 '19 at 09:04

0 Answers0