web-dev-qa-db-ja.com

setDataSource(FileDescriptor)メソッドを呼び出すときの例外(失敗:status = 0x80000000)

私はビデオストリーミングアプリケーションを開発していますが、FileDescriptorでset setDataSourceを呼び出すと動けなくなります。ダウンロード中にアプリケーションでビデオを再生したいので、最小バイト数を取得したら、それらのバイトを別のファイルに移動して、元のファイルでダウンロードされている間に別のファイルで再生できるようにします。

そのため、次のようにパケットごとにメディアペインターを開始できるかどうかを確認します。

if (mediaPlayer == null) {
                    // Only create the MediaPlayer once we have the minimum
                    // buffered data
                    if (totalKbRead >= INTIAL_KB_BUFFER) {
                        try {
                            startMediaPlayer();
                        } catch (Exception e) {
                            Log.e(getClass().getName(),
                                    "Error copying buffered conent.", e);
                        }
                    }
                } else if (mediaPlayer.getDuration()
                        - mediaPlayer.getCurrentPosition() <= 1000) {
                    transferBufferToMediaPlayer();
                }
}

これはstartMediaPlayerメソッドのコードです。

private void startMediaPlayer() {
        try {
            File bufferedFile = new File(context.getCacheDir(), "playingMedia"
                    + (counter++) + ".dat");

            // bufferedFile is the one that'll be played
            moveFile(downloadingMediaFile, bufferedFile);

            mediaPlayer = createMediaPlayer(bufferedFile);

            mediaPlayer.start();

            playButton.setEnabled(true);
        } catch (IOException e) {
            Log.e(getClass().getName(), "Error initializing the MediaPlayer.",
                    e);
            return;
}

次のコードでファイルを移動します。

public void moveFile(File oldLocation, File newLocation) throws IOException {

        if (oldLocation.exists()) {
            BufferedInputStream reader = new BufferedInputStream(
                    new FileInputStream(oldLocation));
            BufferedOutputStream writer = new BufferedOutputStream(
                    new FileOutputStream(newLocation, false));
            try {
                byte[] buff = new byte[8192];
                int numChars;
                while ((numChars = reader.read(buff, 0, buff.length)) != -1) {
                    writer.write(buff, 0, numChars);
                }
            } catch (IOException ex) {
                throw new IOException("IOException when transferring "
                        + oldLocation.getPath() + " to "
                        + newLocation.getPath());
            } finally {
                try {
                    if (reader != null) {
                        writer.flush();
                        writer.close();
                        reader.close();
                    }
                } catch (IOException ex) {
                    Log.e(getClass().getName(),
                            "Error closing files when transferring "
                                    + oldLocation.getPath() + " to "
                                    + newLocation.getPath());
                }
            }
        } else {
            throw new IOException(
                    "Old location does not exist when transferring "
                            + oldLocation.getPath() + " to "
                            + newLocation.getPath());
        }
    }
}

そして、最後にここでMediaPlayerオブジェクトを作成します。

private MediaPlayer createMediaPlayer(File mediaFile) throws IOException {

        if(mediaPlayer != null){
            mediaPlayer.release();
        }

        MediaPlayer mPlayer = new MediaPlayer();
        mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            public boolean onError(MediaPlayer mp, int what, int extra) {
                Log.e(getClass().getName(), "Error in MediaPlayer: (" + what
                        + ") with extra (" + extra + ")");
                return false;
            }
        });

        // It appears that for security/permission reasons, it is better to pass
        // a FileDescriptor rather than a direct path to the File.
        // Also I have seen errors such as "PVMFErrNotSupported" and
        // "Prepare failed.: status=0x1" if a file path String is passed to
        // setDataSource().
        FileInputStream fis = new FileInputStream(mediaFile);

        mPlayer.reset();
        FileDescriptor fd = fis.getFD();
        mPlayer.setDataSource(fd);       // IM GETTING THE EXCEPTION HERE
        mPlayer.setDisplay(mHolder);
        mPlayer.prepare();
        return mPlayer;
    }

これは私が得る例外です:

01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229): Error initializing the MediaPlayer.
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229): Java.io.IOException: setDataSourceFD failed.: status=0x80000000
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.media.MediaPlayer.setDataSource(Native Method)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.media.MediaPlayer.setDataSource(MediaPlayer.Java:854)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at org.pfc.utils.StreamingMediaPlayer.createMediaPlayer(StreamingMediaPlayer.Java:266)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at org.pfc.utils.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.Java:226)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at org.pfc.utils.StreamingMediaPlayer.access$4(StreamingMediaPlayer.Java:203)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at org.pfc.utils.StreamingMediaPlayer$2.run(StreamingMediaPlayer.Java:183)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.os.Handler.handleCallback(Handler.Java:587)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.os.Handler.dispatchMessage(Handler.Java:92)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.os.Looper.loop(Looper.Java:144)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Android.app.ActivityThread.main(ActivityThread.Java:4937)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Java.lang.reflect.Method.invokeNative(Native Method)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at Java.lang.reflect.Method.invoke(Method.Java:521)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:868)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:626)
01-25 16:03:15.663: ERROR/org.pfc.utils.StreamingMediaPlayer(2229):     at dalvik.system.NativeStart.main(Native Method)

午前中ずっとここで立ち往生しており、そのエラーに関する情報は本当に見つかりません。ファイルパスを使用するように言われた人もいますが、コメントで説明している他の例外があります(FileInputStreamの作成のすぐ上)。

私は本当にここで迷ってしまいました。どんな助けも大歓迎です

31
Pedriyoo

さて、次のようなエラーがあるという結論に達しました。

準備に失敗しました:status = 0x1(prepare()を呼び出すとき)

そして

setDataSourceFDが失敗しました:status = 0x80000000(setDataSourceFD()を呼び出すとき)

ファイル形式と関係があり、おそらくファイルが不完全、破損、またはそのようなものであることを意味します...

this リンクに投稿したように、ストリーミング中に問題なく機能する特定のビデオを見つけました(setDataSourceではなくsetDataSourceFDを使用していますが)ほとんどの動画では動作しません。

23
Pedriyoo

許可を忘れないでください

<uses-permission Android:name="Android.permission.INTERNET" /> 
38
Crossle Song

私が読んだものから、特定のビデオファイル形式には、ファイルの終了に関する"header"情報があります。したがって、FDはファイルの末尾から「ヘッダー」を取得するシーク機能をサポートする必要があります。メディアプレーヤーへの入力ファイルがファイルの「最後」にシークすると失敗するのではないかと考えています。

私たちは同じ問題に取り組んでいます、あなたはさらに手に入れましたか?

ショーン

1
Sean

同じエラーが発生し、ファイル形式に関する上記の回答を読んだ後、.movファイルでsetDataSourceをしようとするのを断念し、代わりに.mp4を与えたmy Android Telefon Cameraでビデオを作成しましたこれをディレクトリPictures /に配置しました。これは機能しました-エラーなしでsetDataSourceを作成しました。

File mediaStorageDir = new         File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES),     "MyDirectoryUnderPictures");
File mediaFile_mp4_Android;
mediaFile_mp4_Android = new File(mediaStorageDir.getPath()
                    + File.separator
                    + "mp4_test"
                    + ".mp4"); //video taken with Android camera
String filePath_mp4_Android = String.valueOf(mediaFile_mp4_Android);
File file_mp4_Android = new File(filePath_mp4_Android);
Uri contentUri = Uri.fromFile(file_mp4_Android);
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(String.valueOf(contentUri));
1
Lawn

私の場合、wavファイルからmp3に切り替えると、status = 0x80000000でこの例外が解決されました

0
Hemant

Pedriyooに同意し、異なるビデオファイル形式で例外を再現しようとしましたが、AVI、MPG/MPEG、MOV、mov、mp4、m4v、flv、WMV、AVI、MPG/MPEG、 WMVは毎回例外を投げてくれました。メソッドを実行する前にそれらを除外し、try-catchでラップする方が適切です。

0
waseefakhtar

マシュマロ以上をターゲットにしている場合は、Manifest.permission.WRITE_EXTERNAL_STORAGE適切に許可。 MediaMetadataRetrieverに代わる別のライブラリを含むさまざまなソリューションを試しましたが、コードパスの1つが適切な許可を要求しなかったことがわかりました。

0
hansonchris

Obb拡張ファイルからビデオをロードしているときに、同じ問題に直面していました。私は交換して修正しました:

mPlayer.setDataSource(fd); 

で:

mPlayer.setDataSource(fis.getFileDescriptor(),fis.getStartOffset(),fis.getLength());
0
Usama Saeed US

私の場合、デバイスがpcの外部ストレージとしてマウントされているときにビジー状態のsdカードが原因であったため、ファイルが利用可能かどうかを確認すると問題が解決しました。たぶんそれは誰かを助ける

0
vir us