简体   繁体   English

Android 4.2上的TextureView问题

[英]Issues with TextureView on Android 4.2

Has anyone faced issues with TextureView and MediaPlayer on Android 4.2.2? 有没有人在Android 4.2.2上遇到过TextureView和MediaPlayer的问题?

SOLVED: See answer below and how to serve files from an embedded HTTP server. 已解决:请参阅下面的答案以及如何从嵌入式HTTP服务器提供文件。

UPDATE: The videos which fail to display if embedded in the res/raw folder play just fine if they are hosted online. 更新:如果嵌入在res / raw文件夹中,则无法显示的视频如果在线托管则可以正常播放。 See below for example: 见下面的例子:

// This works
mMediaPlayer.setDataSource("http://someserver.com/test.mp4");
//This does not work. The file is the same as the one above but placed in res/raw.
String vidpath = "android.resource://" + getActivity().getPackageName() + "/" + R.raw.test;
mMediaPlayer.setDataSource(getActivity(), Uri.parse(vidpath));

We need a texture view so we can apply some effects to it. 我们需要一个纹理视图,以便我们可以应用一些效果。 The TextureView is used to display a video from the MediaPlayer. TextureView用于显示MediaPlayer中的视频。 The application works on Android 4.1, 4.3 and 4.4 (on many devices including the old Nexus S up to the Nexus 10 and Note 3) but on 4.2.2 the TextureView becomes black. 该应用程序适用于Android 4.1,4.3和4.4(在许多设备上,包括旧的Nexus S,直到Nexus 10和Note 3),但在4.2.2上,TextureView变为黑色。 There are no errors or exceptions reported by the MediaPlayer and the reported video sizes are correct. MediaPlayer未报告任何错误或异常,并且报告的视频大小正确无误。 Testing a SurfaceView on this particular device displays the video, but then we can't manipulate the view the way we need to. 在此特定设备上测试SurfaceView会显示视频,但我们无法按照需要的方式操作视图。

One interesting bit is that a TextureView works on that device if playing the Nasa Live Streaming Video feed and some other streaming m3u8 files ( http://www.nasa.gov/multimedia/nasatv/NTV-Public-IPS.m3u8 ) but we need to play embedded videos from the raw folder. 一个有趣的是,如果播放Nasa直播视频源和其他一些流媒体m3u8文件( http://www.nasa.gov/multimedia/nasatv/NTV-Public-IPS.m3u8),TextureView可以在该设备上工作,但我们需要播放原始文件夹中的嵌入视频。 We noticed however that at the very top of the TextureView, there's a 4x1 pixel line which keeps blinking some colors very rapidly. 然而,我们注意到在TextureView的最顶部,有一条4x1像素线,可以非常快速地闪烁某些颜色。 I wonder if the media player is rendering the video on that hairline or maybe it is an encoding problem or a hardware issue (this particular 4.2.2 device is a mimic of the iPad mini called... the haiPad >.< (which of course is the client's target device - hate you Murphy)). 我想知道媒体播放器是否正在渲染该网络上的视频,或者这可能是编码问题或硬件问题(这个特殊的4.2.2设备模仿iPad mini称为... haiPad>。<(哪个)当然是客户的目标设备 - 恨你Murphy))。

Here's the info I could gather about the video which is failing to play: 以下是我可以收集的有关视频无法播放的信息:

MPEG-4 (Base Media / Version 2): 375 KiB, 5s 568ms
1 Video stream: AVC
1 Audio stream: AAC
Overall bit rate mode: Variable
Overall bit rate: 551 Kbps
Encoded date: UTC 2010-03-20 21:29:11
Tagged date: UTC 2010-03-20 21:29:12
Writing application: HandBrake 0.9.4 2009112300
Video: 466 Kbps, 560*320 (16:9), at 30.000 fps, AVC (Baseline@L3.0) (2 ref Frames)

Anyone has any pointers? 任何人有任何指针?

For anyone facing similar issues, this is what worked for us. 对于任何面临类似问题的人来说,这对我们有用。

We are still not sure why playing embedded videos with the app does not work. 我们仍然不确定为什么使用应用程序播放嵌入视频无效。 We tried res/raw, assets and copying to the internal storage and sd card. 我们尝试了res / raw,资产和复制到内部存储和SD卡。

Since it was able to play videos from an HTTP server, we ended up embedding a light weight HTTP server within the app to serve the files directly from the assets directory. 由于它能够从HTTP服务器播放视频,我们最终在应用程序中嵌入了轻量级HTTP服务器,以直接从assets目录提供文件。 Here I'm using nanohttpd as an embedded server. 在这里,我使用nanohttpd作为嵌入式服务器。

For it to work, I just need to place the video in the assets folder. 要使它工作,我只需要将视频放在assets文件夹中。 For example assets/animation/animation1.mp4 . 例如assets / animation / animation1.mp4 When referencing the file, you pass "animation/animation1.mp4" as a path and the server will serve the file from the assets directory. 引用文件时,将“animation / animation1.mp4”作为路径传递,服务器将从assets目录中提供文件。

Application class starting the http server and registering it as a service. 应用程序类启动http服务器并将其注册为服务。

public class MyApplication extends Application {

    private NanoServer mNanoServer;

    @Override
    public void onCreate() {

        super.onCreate();
        mNanoServer = new NanoServer(0, getApplicationContext());

        try {

            mNanoServer.start();
        } catch (IOException e) {

            Log.e("Unable to start embeded video file server. Animations will be disabled.",
                    "MyApplication", e);
        }
    }

    @Override
    public void onTerminate() {

        mNanoServer.stop();
        super.onTerminate();
    }

    @Override
    public Object getSystemService(String name) {

        if (name.equals(NanoServer.SYSTEM_SERVICE_NAME)) {
            // TODO Maybe we should check if the server is alive and create a new one if it is not.
            // How often can the server crash?
            return mNanoServer;
        }

        return super.getSystemService(name);
    }
}

The NanoServer class NanoServer类

/*
 * TODO Document this.
 */
public class NanoServer extends NanoHTTPD {

    public static final String SYSTEM_SERVICE_NAME = "NANO_EMBEDDED_SYSTEM_HTTP_SERVER";
    private Context mContext;

    public NanoServer(int port, Context context) {
        super(port);
        this.mContext = context;
    }

    public NanoServer(String hostname, int port) {
        super(hostname, port);
    }

    @Override
    public Response serve(IHTTPSession session) {

        try {

            Uri uri = Uri.parse(session.getUri());
            String fileToServe = normalizePath(uri.getPath());

            return new Response(Status.OK, "video/mp4", (InputStream) mContext.getAssets().open(fileToServe));
        } catch (IOException e) {

            return new Response(Status.INTERNAL_ERROR, "", "");
        }
    }

    private String normalizePath(String path) {

        return path.replaceAll("^/+", "");
    }

    public String getUrlFor(String filePath) {

        return String.format(Locale.ENGLISH, "http://localhost:%d/%s", getListeningPort(), filePath);
    }
}

Using it in a Fragment 在片段中使用它

if (fileToPlay != null) {

    mTextureView = (TextureView) inflatedView.findViewById(R.id.backgroundAnimation);
    mTextureView.setSurfaceTextureListener(new VideoTextureListener());
}

...

private final class VideoTextureListener implements SurfaceTextureListener {
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {

        mMediaPlayer.release();
        mMediaPlayer = null;
        return true;
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

        Surface s = new Surface(surface);

        try {

            NanoServer server =
                    (NanoServer) getActivity().getApplication().getSystemService(NanoServer.SYSTEM_SERVICE_NAME);
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setSurface(s);
            mMediaPlayer.setDataSource(server.getUrlFor(mHotspotTemplate.animation));
            mMediaPlayer.prepareAsync();
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setVolume(0, 0);

            mMediaPlayer.setOnErrorListener(new OnErrorListener() {

                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {

                    mMediaPlayer.release();
                    mTextureView.setVisibility(View.INVISIBLE);
                    return true;
                }
            });
            mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {

                @Override
                public void onPrepared(MediaPlayer mp) {

                    mMediaPlayer.start();
                }
            });

            mMediaPlayer.setLooping(true);
            mMediaPlayer.setVolume(0, 0);
        } catch (Throwable e) {

            if (mMediaPlayer != null) {

                mMediaPlayer.release();
            }

            mTextureView.setVisibility(View.INVISIBLE);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM