The goal I have is to broadcast to a RTMP server and that is going perfect in landscape mode. When I record in portrait mode, the resolution remains the same as in landscape (1280x720) and to prevent the video from becoming stretched out, I use the FFmpegFrameFilter to make changes to the video. I rotate the image, scale it and set padding to 'simulate' black bars like this:
filter = new FFmpegFrameFilter("transpose=2, scale=480:720, pad=1280:720:400:0:color=black", imageWidth, imageHeight);
The size of the new video looks about right, but the video is in black and white instead of color and there are green/purple blurs on the left/right edges of the video.
I have set the pixel format to AV_PIX_FMT_NV21, but that does not resolve the issue. If I delete the "pad=1280:720:400:0:color=black" part, the video does remain in color, but the image is all stretched out.
Once the orientation changes:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(recorder != null) {
if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
filter = new FFmpegFrameFilter("transpose=2, scale=-1:720", imageWidth, imageHeight);
filter.setPixelFormat(avutil.AV_PIX_FMT_NV21); // default camera format on Android
try {
filter.start();
} catch (FrameFilter.Exception e) {
e.printStackTrace();
}
}
else {
filter = null;
}
}
}
OnPreviewFrame:
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (audioRecord == null || audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
startTime = System.currentTimeMillis();
return;
}
if (RECORD_LENGTH > 0) {
int i = imagesIndex++ % images.length;
yuvImage = images[i];
timestamps[i] = 1000 * (System.currentTimeMillis() - startTime);
}
/* get video data */
if (yuvImage != null && recording) {
((ByteBuffer)yuvImage.image[0].position(0)).put(data);
if (RECORD_LENGTH <= 0) try {
Log.v(LOG_TAG,"Writing Frame");
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
if(filter != null) {
try {
filter.push(yuvImage);
Frame frame;
while ((frame = filter.pull()) != null) {
recorder.record(frame);
}
} catch (FrameFilter.Exception e) {
e.printStackTrace();
}
}
else {
recorder.record(yuvImage);
}
} catch (FFmpegFrameRecorder.Exception e) {
Log.v(LOG_TAG,e.getMessage());
e.printStackTrace();
}
}
}
}
Do you have any suggestions?
Is this an issue with FFmpegFrameFilter? Or is it a question about FFmpeg filters?
This is not a question about FFmpeg filters, but a question about FFmpegFrameFilter. I just tried a similar command with regular FFmpeg and it worked fine, so looks like it's an issue with FFmpegFrameFilter.
I know some filters don't support all pixel formats very well, so you might want to try and use a different one. It's possible to do conversion within the graph with the format filter:
https://ffmpeg.org/ffmpeg-filters.html#format-1
https://github.com/bytedeco/javacv/issues/232#issuecomment-162601656
Have you been able to find the right combination of filters to get this working?
Hi,
No I've been unable to get it working. In the end I've decided to use Kickflip for my project.
Thanks for your help though!
I'm also experiencing the same issue. I've been trying all sorts of combinations of filters and formats, so far no luck.
Did anybody find a decent solution for this?
Try to put "format=rgba" and/or "format=bgr24" filters at various stages in the graph...
Hey thanks @saudet , turns out the problem was in the "pad" filter (perhaps it's a support issue with the pixel formats like you suggested)...
I've ended up using the "crop" filter instead, which works very nicely. Here's my full portrait mode filter so far:
String transpose = cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT ? "2" : "1";
String scale = "-1:ih";
String crop = "iw:ih:(ow-iw)/2:0";
filter = new FFmpegFrameFilter("transpose=" + transpose + ", scale=" + scale + ", crop=" + crop, imageWidth, imageHeight);
filter.setPixelFormat(avutil.AV_PIX_FMT_NV21);
Most helpful comment
Hey thanks @saudet , turns out the problem was in the "pad" filter (perhaps it's a support issue with the pixel formats like you suggested)...
I've ended up using the "crop" filter instead, which works very nicely. Here's my full portrait mode filter so far: