找茬小王子 2023-12-14 14:43 采纳率: 50%
浏览 15
已结题

安卓上层打开dev/video11并播放视频流

我的代码运行之后好像没有获取到视频流的数据一直无法播放,我想知道是什么原因,我的流程有问题还是播放地址有问题,该如何解决?

package com.example.sditest;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
import android.util.Size;
import android.view.Surface;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;

public class MediaThread extends Thread {
    private Surface surface;
    private MediaCodec mediaCodec;
    private MediaFormat mformat;
    private String mime = null;

    private int width = 0; // 视频宽度
    private int height = 0; // 视频高度

    private Size preSize;

    private Process process = null;
    private DataOutputStream os = null;
    private long startMs = -1;
    private ByteBuffer[] inputBuffers;
    private boolean runing = false;
    private String inout = null;



    public MediaThread(Surface surface, Size size, Size preSize, String inout) {
        this.surface = surface;
        width = size.getWidth();
        height = size.getHeight();
        this.inout = inout;
        this.preSize = preSize;
    }

    //初始化MediaCodec
    public void extractor() {
        try {
            mediaCodec = MediaCodec.createDecoderByType("video/avc");
            mformat = MediaFormat.createVideoFormat("video/avc", width, height);
            mediaCodec.configure(mformat, surface, null, 0);
            mediaCodec.start();
            inputBuffers = mediaCodec.getInputBuffers();
            runing =true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void showSdi(byte[] data){

    }

    public void showHdmi(byte[] data){
        Log.d("MediaThread", "开始解码 HDMI IN");
        int inputBufferIndex = mediaCodec.dequeueInputBuffer(10000);
        if (inputBufferIndex >= 0) {
            ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
            inputBuffer.clear();
            inputBuffer.put(data);
            mediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
        }

        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
        if (outputBufferIndex >= 0) {
            //保持播放的速度与实际帧率相同
            while (bufferInfo.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
        }
    }

    public void execCommand(String cmd) {
        try {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(cmd + "\n");
            os.writeBytes("exit\n");
            os.flush();

            extractor();

            char[] buff = new char[1024];
            int ch = 0;
            BufferedReader bfsd = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuffer sbs = new StringBuffer();
            runing = true;
            while ((ch = bfsd.read(buff)) != -1 && runing) {
                Log.d("MediaThread", "获取视频帧数据");
                sbs.append(buff, 0, ch);
                Log.d("buffer", sbs.toString().getBytes().length + "\n");

                byte[] data = sbs.toString().getBytes();

                if (inout.equals("sdi")) {
                    showSdi(data);
                }
                if (inout.equals("hdmi")) {
                    showHdmi(data);
                }
            }

            mediaCodec.stop();
            mediaCodec.release();
            surface.release();

            bfsd.close();
            os.close();
            process.destroy();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Log.d("MediaThread", "开始进入播放线程");
        String sdi_cmd2 = "v4l2-ctl --verbose -d /dev/video0 --set-fmt-video=width=" + width + ",height=" + height + ",pixelformat='YUYV' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=" + preSize.getWidth() + ",height=" + preSize.getHeight();
        String hdmi_cmd2 = "v4l2-ctl --verbose -d /dev/video11 --set-fmt-video=width=" + width + ",height=" + height + ",pixelformat='NV12' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=" + preSize.getWidth() + ",height=" + preSize.getHeight();

        if (inout.equals("sdi")) {
            execCommand(sdi_cmd2);
        }
        Log.d("MediaThread",hdmi_cmd2);
        if (inout.equals("hdmi")) {
            execCommand(hdmi_cmd2);
        }

    }

    public void stopTheard(){
        runing = false;
    }
}


运行后的log:

D/MediaThread: 开始进入播放线程
    v4l2-ctl --verbose -d /dev/video11 --set-fmt-video=width=1920,height=1080,pixelformat='NV12' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=1920,height=876
D/MediaCodecList: codecHandlesFormat: no format, so no extra checks
    codecHandlesFormat: no format, so no extra checks
    codecHandlesFormat: no format, so no extra checks
D/CCodec: allocate(c2.rk.avc.decoder)
I/Codec2Client: Available Codec2 services: "default" "software"
I/CCodec: setting up 'default' as default (vendor) store
I/CCodec: Created component [c2.rk.avc.decoder]
D/CCodecConfig: read media type: video/avc
D/ReflectedParamUpdater: extent() != 1 for single value type: output.subscribed-indices.values
    extent() != 1 for single value type: input.buffers.allocator-ids.values
    extent() != 1 for single value type: output.buffers.allocator-ids.values
    extent() != 1 for single value type: output.buffers.pool-ids.values
D/ReflectedParamUpdater: ignored struct field coded.color-format.locations
D/CCodecConfig: ignoring local param raw.size (0xd2001800) as it is already supported
    ignoring local param default.color (0x5200180b) as it is already supported
D/ReflectedParamUpdater: ignored struct field raw.hdr-static-info.mastering
I/CCodecConfig: query failed after returning 12 values (BAD_INDEX)
D/CCodecConfig: c2 config diff is Dict {
      c2::u32 algo.low-latency.value = 0
      c2::u32 coded.pl.level = 20495
      c2::u32 coded.pl.profile = 20480
      c2::u32 coded.vui.color.matrix = 0
      c2::u32 coded.vui.color.primaries = 0
      c2::u32 coded.vui.color.range = 2
      c2::u32 coded.vui.color.transfer = 0
      c2::u32 default.color.matrix = 0
      c2::u32 default.color.primaries = 0
      c2::u32 default.color.range = 0
      c2::u32 default.color.transfer = 0
      c2::u32 input.buffers.max-size.value = 2097152
      string input.media-type.value = "video/avc"
      c2::u32 output.delay.value = 16
      string output.media-type.value = "video/raw"
      c2::u32 raw.color.matrix = 0
      c2::u32 raw.color.primaries = 0
      c2::u32 raw.color.range = 2
      c2::u32 raw.color.transfer = 0
      c2::u32 raw.max-size.height = 240
      c2::u32 raw.max-size.width = 320
      c2::u32 raw.pixel-format.value = 35
      c2::i32 raw.rotation.flip = 0
      c2::i32 raw.rotation.value = 0
      c2::u32 raw.sar.height = 1
      c2::u32 raw.sar.width = 1
      c2::u32 raw.size.height = 240
      c2::u32 raw.size.width = 320
W/ColorUtils: expected specified color aspects (2:0:0:0)
D/SurfaceUtils: connecting to surface 0x771fd30110, reason connectToSurface
I/MediaCodec: [c2.rk.avc.decoder] setting surface generation to 10882049
D/SurfaceUtils: disconnecting from surface 0x771fd30110, reason connectToSurface(reconnect)
    connecting to surface 0x771fd30110, reason connectToSurface(reconnect)
D/CCodec: [c2.rk.avc.decoder] buffers are bound to CCodec for this session
D/CCodecConfig: no c2 equivalents for native-window
    no c2 equivalents for flags
    config failed => CORRUPTED
D/CCodecConfig: c2 config diff is   c2::u32 raw.size.height = 1080
      c2::u32 raw.size.width = 1920
W/Codec2Client: query -- param skipped: index = 1107298332.
D/CCodec: setup formats input: AMessage(what = 0x00000000) = {
      int32_t height = 1080
      int32_t level = 32768
      int32_t max-input-size = 2097152
      string mime = "video/avc"
      int32_t profile = 1
      int32_t width = 1920
      Rect crop(0, 0, 1919, 1079)
    }
    setup formats output: AMessage(what = 0x00000000) = {
      int32_t android._color-format = 2135033992
      int32_t android._video-scaling = 1
      int32_t rotation-degrees = 0
      int32_t color-standard = 1
      int32_t color-range = 2
      int32_t color-transfer = 3
      int32_t sar-height = 1
      int32_t sar-width = 1
      Rect crop(0, 0, 1919, 1079)
      int32_t width = 1920
      int32_t height = 1080
      int32_t max-height = 240
      int32_t max-width = 320
      string mime = "video/raw"
      int32_t android._dataspace = 260
      int32_t color-format = 2130708361
    }
I/CCodecConfig: query failed after returning 12 values (BAD_INDEX)
D/CCodecConfig: c2 config diff is   c2::u32 raw.max-size.height = 1080
      c2::u32 raw.max-size.width = 1920
W/Codec2Client: query -- param skipped: index = 1342179345.
    query -- param skipped: index = 2415921170.
    query -- param skipped: index = 1073743886.
    query -- param skipped: index = 1610614798.
    query -- param skipped: index = 2684356609.
D/C2Store: Using DMABUF Heaps
D/CCodecBufferChannel: [c2.rk.avc.decoder#257] Created input block pool with allocatorID 16 => poolID 17 - OK (0)
D/CCodecBufferChannel: [c2.rk.avc.decoder#257] Configured output block pool ids 20 => OK
D/Codec2-OutputBufferQueue: remote graphic buffer migration 0/0
D/Codec2Client: setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
    setOutputSurface -- generation=10882049 consumer usage=0x900
D/Codec2Client: Surface configure completed
I/DMABUFHEAPS: Using DMA-BUF heap named: system

推流命令从shell执行的结果:

rk3588s_s:/ # su
rk3588s_s:/ # v4l2-ctl --verbose -d /dev/video11 --set-fmt-video=width=1920,height=1080,pixelformat='NV12' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=1920,height=876
VIDIOC_QUERYCAP: ok
VIDIOC_G_FMT: ok
VIDIOC_S_FMT: ok
Format Video Capture Multiplanar:
        Width/Height      : 1920/1080
        Pixel Format      : 'NV12'
        Field             : None
        Number of planes  : 1
        Flags             :
        Colorspace        : Default
        Transfer Function : Default
        YCbCr Encoding    : Default
        Quantization      : Default
        Plane 0           :
           Bytes per Line : 1920
           Size Image     : 3110400
VIDIOC_G_SELECTION: ok
VIDIOC_S_SELECTION: failed: Inappropriate ioctl for device
VIDIOC_REQBUFS: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_QUERYBUF: ok
VIDIOC_QBUF: ok
VIDIOC_STREAMON: ok
idx: 0 seq:      0 bytesused: 3110400 ts: 21003.165904
idx: 1 seq:      1 bytesused: 3110400 ts: 21003.182595 delta: 16.691 ms
idx: 2 seq:      2 bytesused: 3110400 ts: 21003.199244 delta: 16.649 ms
idx: 3 seq:      3 bytesused: 3110400 ts: 21003.215906 delta: 16.662 ms
idx: 0 seq:      4 bytesused: 3110400 ts: 21003.232608 delta: 16.702 ms fps: 59.97
idx: 1 seq:      5 bytesused: 3110400 ts: 21003.249229 delta: 16.621 ms fps: 60.01
idx: 2 seq:      6 bytesused: 3110400 ts: 21003.265918 delta: 16.689 ms fps: 59.99
idx: 3 seq:      7 bytesused: 3110400 ts: 21003.282575 delta: 16.657 ms fps: 60.00
idx: 0 seq:      8 bytesused: 3110400 ts: 21003.299255 delta: 16.680 ms fps: 59.99
idx: 1 seq:      9 bytesused: 3110400 ts: 21003.315906 delta: 16.651 ms fps: 60.00
idx: 2 seq:     10 bytesused: 3110400 ts: 21003.332585 delta: 16.679 ms fps: 59.99
idx: 3 seq:     11 bytesused: 3110400 ts: 21003.349231 delta: 16.646 ms fps: 60.00
idx: 0 seq:     12 bytesused: 3110400 ts: 21003.365890 delta: 16.659 ms fps: 60.00
idx: 1 seq:     13 bytesused: 3110400 ts: 21003.382563 delta: 16.673 ms fps: 60.00
idx: 2 seq:     14 bytesused: 3110400 ts: 21003.399239 delta: 16.676 ms fps: 60.00
idx: 3 seq:     15 bytesused: 3110400 ts: 21003.415894 delta: 16.655 ms fps: 60.00
idx: 0 seq:     16 bytesused: 3110400 ts: 21003.432586 delta: 16.692 ms fps: 60.00

  • 写回答

12条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-12-14 14:44
    关注

    引自强大而免费的微信小程序:皆我知道

    要解决这个问题,你可以按照以下步骤进行排查:

    1. 确认设备是否具有/dev/video11这个设备节点:可以通过运行ls /dev/video*命令来查看设备节点列表。如果没有找到/dev/video11节点,可能是因为设备不存在或者设备权限不正确。你可以尝试使用chmod命令修改设备权限,并确保设备已连接并可用。

    2. 检查你的代码逻辑是否正确:请提供你的代码以供检查。确保你正确地打开设备节点并成功获取到视频流数据。你也可以尝试使用其他视频流播放器来验证视频流是否可用。

    3. 确认播放地址是否正确:你所使用的播放地址可能有问题,导致播放器无法获取到视频流数据。请检查播放地址是否正确,并确保服务器或源设备上存在有效的视频流。

    4. 检查网络连接和防火墙设置:如果你的视频流来自网络源,那么请确保你的设备可以与源设备建立正确的网络连接,并且没有任何防火墙或路由器设置阻止视频流的传输。

    根据你提供的信息,目前很难确定问题出在哪里。提供更多详细的信息和代码段将帮助我们更好地理解问题并给出解决方案。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月18日
  • 创建了问题 12月14日

悬赏问题

  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改
  • ¥15 Windows 系统cmd后提示“加载用户设置时遇到错误”
  • ¥50 vue router 动态路由问题
  • ¥15 关于#.net#的问题:End Function
  • ¥15 无法import pycausal
  • ¥15 weditor无法连接模拟器Local server not started, start with?
  • ¥20 6-3 String类定义
  • ¥15 嵌入式--定时器使用