I want to record video only in android with MPEG4 format. I want the container and codec to be MPEG4. So here is what I have done for that.
Thread video = new Thread(new Runnable() {
public void run() {
videoRecorder = new MediaRecorder();
videoRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
videoRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
videoRecorder.setVideoEncodingBitRate(56 * 8 * 1024);
videoRecorder.setVideoSize(176, 144);
videoRecorder.setVideoFrameRate(12);
videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
videoRecorder.setOutputFile("/sdcard/video.m4e");
try {
videoRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
videoRecorder.start();
}
});
video.start();
Now, after recording, I got the video recorded into video.m4e file. But when I check its information, I got the following:
At the same time I used the following to record audio:
Thread audio = new Thread(new Runnable() {
public void run() {
audioRecorder = new MediaRecorder();
audioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
audioRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
audioRecorder.setOutputFile("/sdcard/audio.amr");
try {
audioRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
audioRecorder.start();
}
});
audio.start();
and I got the container format and codec as AMR as I intended:
So, what causes MediaRecorder to record video in 3GP format? I haven't specified 3GP anywhere in my program. I am testing this code on my Samsung Galaxy tab running Android 2.2
MPEG-4 is a method of defining compression of audio and visual (AV) digital data.A file format for storing time-based media content. It is a general format forming the basis for a number of other more specific file formats (e.g. 3GP, Motion JPEG 2000, MPEG-4 Part 14).So there is no conspiracy in the result you got, the compression method (OR "Codec") you used was MPEG4 and the video format generated by your phone is 3gp, which in actual is a part of the video formats of the suite of the MPEG4 compression scheme for the media.
This is defined by the frameworks. Specifically it has a set of parameters that are found in the MediaRecorder class that define what all is supported.
I do not understand akkilis's explanation.
In the official Android tutorial "MediaRecorder.OutputFormat",
MPEG_4 is one of options of "media file formats", parallel to THREE_GPP.
int AAC_ADTS AAC ADTS file format
int AMR_NB AMR NB file format
int AMR_WB AMR WB file format
int DEFAULT
int MPEG_4 MPEG4 media file format
int RAW_AMR This constant was deprecated in API level 16. Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
int THREE_GPP 3GPP media file format
There is another parameter to specify the encoding format:
"MediaRecorder.VideoEncoder"
int DEFAULT
int H263
int H264
int MPEG_4_SP
In OP's code, he specified both file format and encoding format.
videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
So it seems akkilis's explanation does not work for this example.
Related
I am trying to make an AirPlay server in java with this library. I am able to start the server and connect to it and I am getting video input, however the input is in h264 format and I tried decoding it with JCodec but it always says I need an sps/pps and I don't know how to create/find this with just a byte[]. This is the onVideo method which is pretty much just copy-pasted from some websites:
#Override
public void onVideo(byte[] video) {
try {
videoFileChannel.write(ByteBuffer.wrap(video));
ByteBuffer bb = ByteBuffer.wrap(video);
H264Decoder decoder = new H264Decoder();
decoder.addSps(List.of(ByteBuffer.wrap(video)));
Picture out = Picture.create(1920, 1088, ColorSpace.YUV420);
var real = decoder.decodeFrame(bb, out.getData());
// decoder.decodeFrame prints "[WARN] . (:0): Skipping frame as no SPS/PPS have been seen so far..." in console and returns null => NullPointer in next line
var img = AWTUtil.toBufferedImage(real.createCompatible());
// ...
} catch (IOException e) {
e.printStackTrace();
}
}
Edit: I've uploaded a ("working") version to github, but the decoded image is discolored and doesn't update all pixels so when something is on the screen and the frame changes, that something can still be on the image.
I am trying to download a video (with a Xuggler 5.4 library) from rtsp stream to a file using the code below.
String inputSource = "rtsp://[ip-address]:[port]/user=[username]&[password]=password&channel=1&stream=1.sdp";
String outputFilename = "d:/downloadedrtsp.flv";
try {
IContainerFormat inFormat = IContainerFormat.make();
inFormat.setInputFormat("h246");
IMediaReader mediaReader = ToolFactory.makeReader(inputSource);
mediaReader.setQueryMetaData(false);
IMediaWriter mediaWriter = ToolFactory.makeWriter(outputFilename, mediaReader);
mediaReader.addListener(mediaWriter);
logger.info("before reading");
IError error;
while ((error = mediaReader.readPacket()) == null) {
logger.info("reading packet");
}
logger.info("error: " + error.getDescription());
logger.info(error.getType());
logger.info(error.toString());
} catch (Exception e) {
e.printStackTrace();
}
The problem is that after printing "before reading" the code just stop executing, and after a long time it prints me three lines from logger:
error: Unknown error
ERROR_EOF
Unknown error
Stream works great when i am opening it in the VLC media player. I am shure there is some mistake in my mediaReader configuration, but i don't know where exactly as i have a very little experience working with videos. Here is some information about video, taken from VLC:
It seems like everything works as expected.
The error type ERROR_EOF marks the end of the input stream (see the documentation).
The long time you program "stop executing" is the time it takes for Xuggler to convert the video frames (it actually doesn't "stop", just iterate through the while loop).
I've been trying to figure out for the life of me how to cut up a certain amount of milliseconds out of a sample. My first problem is when I insert this code into eclipse. It tells me AudioInputStream, AudioFileFormat and FileFormat are not available. If I can't use FileFormat then i can't pass methods into other methods to get the correct calculations to save the correct amount of music. I can't even import them. But more importantly, how can I change the parameter "secondstocopy" into "millisecondstocopy" without ruining the integrity of the algorithm? Still new to java, thank you for your help!
//edit// FileFormat fileFormat = AudioSystem.getAudioFileFormat(file); It seems I can't use this bit of code for android. The getAudioFileFormat doesn't work. Nor can I calculate the fram rate because of.. int bytesPerSecond = format. * (int)format.getFrameRate(); How do I properly get the format and frame rate with media player so that I can calculate the bytesPerSecond and secondsToCopy?
AudioSystem is part of JavaSound, and JavaSound is part of the desktop JVM/SDK. JavaSound is NOT present in the Android JVM/SDK, so your old code will not compile on any current Android SDK. I get an exception using java on android (java.lang.NoClassDefFoundError), why?
How can I calculate the file format and fram rate and stuff without the javasound jvm/sdk. I can tell you now that the sounds are 44100 and 16 bit something. In the get info pane of the recording file, it says total bit rate: 128,000 with two audio channels. I'm not good with encoding stuff but I'm recording the audio with a program on mac called wiretap pro. It tells me the the parameters.
import java.io.*;
import javax.sound.sampled.*;
class AudioFileProcessor {
public static void main(String[] args) {
copyAudio("/tmp/uke.wav", "/tmp/uke-shortened.wav", ƒ, 1);
}
public static void copyAudio(String sourceFileName, String destinationFileName, int startSecond, int secondsToCopy) {
AudioInputStream inputStream = null;
AudioInputStream shortenedStream = null;
try {
File file = new File(sourceFileName);
AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
AudioFormat format = fileFormat.getFormat();
inputStream = AudioSystem.getAudioInputStream(file);
int bytesPerSecond = format.getFrameSize() * (int)format.getFrameRate();
inputStream.skip(startSecond * bytesPerSecond);
long framesOfAudioToCopy = secondsToCopy * (int)format.getFrameRate();
shortenedStream = new AudioInputStream(inputStream, format, framesOfAudioToCopy);
File destinationFile = new File(destinationFileName);
AudioSystem.write(shortenedStream, fileFormat.getType(), destinationFile);
} catch (Exception e) {
println(e);
} finally {
if (inputStream != null) try { inputStream.close(); } catch (Exception e) { println(e); }
if (shortenedStream != null) try { shortenedStream.close(); } catch (Exception e) { println(e); }
}
}
}
this code was taken from: cutting a wave file
I'm working on a project for a programming class, and I want to add a video file. I've tried using JMF, except when I try to play a video (using one of the formats listed on the Java website), it gives me the error:
Unable to handle format: XVID, 320x213, FrameRate=29.9, Length=204480 0 extra bytes
Unable to handle format: mpeglayer3, 22050.0 Hz, 0-bit, Stereo, Unsigned, 8000.0 framerate,FrameSize=4608 bits
Failed to realize: com.sun.media.PlaybackEngine#39b27b
Error: Unable to realize com.sun.media.PlaybackEngine#39b27b
Could not realize media player
This is the code I use to test the player:
public MediaPanel(String path) {
try {
videoPath = new File(path).toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
setLayout(new BorderLayout());
Manager.setHint(Manager.LIGHTWEIGHT_RENDERER, true);
try {
Player mediaPlayer = Manager.createRealizedPlayer(videoPath);
Component video = mediaPlayer.getVisualComponent();
Component controls = mediaPlayer.getControlPanelComponent();
if (video != null)
add(video, BorderLayout.CENTER);
if (controls != null)
add(controls, BorderLayout.SOUTH);
mediaPlayer.start();
} catch (NoPlayerException NoPlayerException) {
System.err.println("No media player found");
} catch (CannotRealizeException CannotRealizeException) {
System.err.println("Could not realize media player");
} catch (IOException IOException) {
System.err.println("Error reading from the source");
}
}
MediaPanel player = new MediaPanel("intro.avi");
I assume my two options are to make a video with the exact specifications listed on the Java website (because apparently just the file extension isn't enough), or use another method to display video.
How can I fix this? Do I need to make a video exactly as the specifications note (see link at bottom)?
NOTE: The class I'm in uses and older version of java that DOESN'T contain javaFX. Please don't recommend this unless there is a way I can add it without having the school reinstall a newer version of Java.
How to create a media player in Java without using the JMF? Some blogs say it's an old version. I also tried using JMF - this is my code.
public class MediaPlayer {
public static void main(String[] args) {
Player p;
try {
p = Manager.createPlayer(new URL("http://192.168.1.113/asmitha/1.mp4"));
p.start();
} catch (NoPlayerException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the message I am getting:
LINEAR, Unknown Sample Rate * out * LINEAR, 8000.0 Hz, 16-bit, Stereo, LittleEndian, Signed, class [S
JMF 2.1 is the latest version, and that was released a long time ago. JMF will probably not support all codec formats. That is probably why you are not able to play the file. There are also a lot of codec licensing issues.
There is a JMF performance pack for windows & *nix which will support more codecs than the default installation. Try that. If that doesn't work take a look at ffmpeg or VLC-J.