Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61c74c6a authored by Hangyu Kuang's avatar Hangyu Kuang
Browse files

media: Add new MediaMuxer constructor that takes FileDescriptor.

Test: Run new mediamuxer CTS test.
Bug: 34221063
Change-Id: Iaad4f0254782dca3e5994e80af0848482847c618
parent 8f3b174d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21752,6 +21752,7 @@ package android.media {
  public final class MediaMuxer {
    ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
    method public int addTrack(android.media.MediaFormat);
    method public void release();
    method public void setLocation(float, float);
+1 −0
Original line number Diff line number Diff line
@@ -23309,6 +23309,7 @@ package android.media {
  public final class MediaMuxer {
    ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
    method public int addTrack(android.media.MediaFormat);
    method public void release();
    method public void setLocation(float, float);
+1 −0
Original line number Diff line number Diff line
@@ -21842,6 +21842,7 @@ package android.media {
  public final class MediaMuxer {
    ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
    method public int addTrack(android.media.MediaFormat);
    method public void release();
    method public void setLocation(float, float);
+29 −8
Original line number Diff line number Diff line
@@ -95,7 +95,8 @@ final public class MediaMuxer {
    public @interface Format {}

    // All the native functions are listed here.
    private static native long nativeSetup(@NonNull FileDescriptor fd, int format);
    private static native long nativeSetup(@NonNull FileDescriptor fd, int format)
            throws IllegalArgumentException, IOException;
    private static native void nativeRelease(long nativeObject);
    private static native void nativeStart(long nativeObject);
    private static native void nativeStop(long nativeObject);
@@ -134,19 +135,13 @@ final public class MediaMuxer {
        if (path == null) {
            throw new IllegalArgumentException("path must not be null");
        }
        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                format != OutputFormat.MUXER_OUTPUT_WEBM) {
            throw new IllegalArgumentException("format is invalid");
        }
        // Use RandomAccessFile so we can open the file with RW access;
        // RW access allows the native writer to memory map the output file.
        RandomAccessFile file = null;
        try {
            file = new RandomAccessFile(path, "rws");
            FileDescriptor fd = file.getFD();
            mNativeObject = nativeSetup(fd, format);
            mState = MUXER_STATE_INITIALIZED;
            mCloseGuard.open("release");
            setUpMediaMuxer(fd, format);
        } finally {
            if (file != null) {
                file.close();
@@ -154,6 +149,32 @@ final public class MediaMuxer {
        }
    }

    /**
     * Constructor.
     * Creates a media muxer that writes to the specified FileDescriptor. File descriptor
     * must be seekable and writable. Application should not use the file referenced
     * by this file descriptor until {@link #stop}. It is the application's responsibility
     * to close the file descriptor. It is safe to do so as soon as this call returns.
     * @param fd The FileDescriptor of the output media file.
     * @param format The format of the output media file.
     * @see android.media.MediaMuxer.OutputFormat
     * @throws IllegalArgumentException if fd is invalid or format is not supported.
     * @throws IOException if failed to open the file for write.
     */
    public MediaMuxer(@NonNull FileDescriptor fd, @Format int format) throws IOException {
        setUpMediaMuxer(fd, format);
    }

    private void setUpMediaMuxer(@NonNull FileDescriptor fd, @Format int format) throws IOException {
        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                format != OutputFormat.MUXER_OUTPUT_WEBM) {
            throw new IllegalArgumentException("format: " + format + " is invalid");
        }
        mNativeObject = nativeSetup(fd, format);
        mState = MUXER_STATE_INITIALIZED;
        mCloseGuard.open("release");
    }

    /**
     * Sets the orientation hint for output video playback.
     * <p>This method should be called before {@link #start}. Calling this
+25 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@
#include "jni.h"
#include "JNIHelp.h"

#include <unistd.h>
#include <fcntl.h>

#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -138,6 +141,28 @@ static jlong android_media_MediaMuxer_native_setup(
    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    ALOGV("native_setup: fd %d", fd);

    // It appears that if an invalid file descriptor is passed through
    // binder calls, the server-side of the inter-process function call
    // is skipped. As a result, the check at the server-side to catch
    // the invalid file descritpor never gets invoked. This is to workaround
    // this issue by checking the file descriptor first before passing
    // it through binder call.
    int flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        ALOGE("Fail to get File Status Flags err: %s", strerror(errno));
        jniThrowException(env, "java/lang/IllegalArgumentException",
                "Invalid file descriptor");
        return 0;
    }

    // fd must be in read-write mode or write-only mode.
    if ((flags & (O_RDWR | O_WRONLY)) == 0) {
        ALOGE("File descriptor is not in read-write mode or write-only mode");
        jniThrowException(env, "java/io/IOException",
                "File descriptor is not in read-write mode or write-only mode");
        return 0;
    }

    MediaMuxer::OutputFormat fileFormat =
        static_cast<MediaMuxer::OutputFormat>(format);
    sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);