我需要在没有MediaExtractor的情况下使用MediaCodec,我正在使用FileInputStream读取文件.目前它不工作,它在屏幕上显示绿色的乱码图像.
这是完整的源代码:
FileInputStream in = new FileInputStream("/sdcard/sample.ts");
String mimeType = "video/avc";
MediaCodec decoder = MediaCodec.createDecoderByType(mimeType);
MediaFormat format = MediaFormat.createVideoFormat(mimeType, 1920, 1080);
byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 };
byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 };
format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
format.setInteger("durationUs", 63446722); …Run Code Online (Sandbox Code Playgroud) 我想在Android设备上显示H.264编码的rtsp视频.该流来自Raspberry Pi,使用vlc编码/dev/video1,这是一个"Pi NoIR相机板".
vlc-wrapper -vvv v4l2:///dev/video1 --v4l2-width $WIDTH --v4l2-height $HEIGHT --v4l2-fps ${FPS}.0 --v4l2-chroma h264 --no-audio --no-osd --sout "#rtp{sdp=rtsp://:8000/pi.sdp}" :demux=h264 > /tmp/vlc-wrapper.log 2>&1
Run Code Online (Sandbox Code Playgroud)
我现在正在使用非常少的Android代码:
final MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDisplay(holder);
try {
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
Run Code Online (Sandbox Code Playgroud)
并获得"准备失败:状态= 0x1" IOException.当我查看日志时,我会看到类似的行
06-02 16:28:05.566 W/APacketSource( 316): Format:video 0 RTP/AVP 96 / MIME-Type:H264/90000
06-02 16:28:05.566 W/MyHandler( 316): Unsupported format. Ignoring track #1.
06-02 16:28:05.566 I/MyHandler( 316): SETUP(1) completed with result -1010 (Unknown error 1010)
Run Code Online (Sandbox Code Playgroud)
来自系统过程.Grepping这些消息指向 libstagefright/rtsp源,似乎意味着构造函数中的ASessionDescription::getDimensions调用APacketSource::APacketSource失败.这似乎不应该发生,因为VLC肯定知道要输出的维度: …
TL; DR:我想从AVI/MP4文件读取原始的h264流,甚至是破坏/不完整的.
几乎所有关于h264的文档都告诉我它包含NAL数据包.好的.几乎每个地方都告诉我,数据包应该以像00 00 01或者签名开头00 00 00 01.例如,https://stackoverflow.com/a/18638298/8167678,/sf/answers/1233787621/
H.264的格式是它由NAL单元组成,每个NAL单元的起始前缀为三个字节,值为0x00,0x00,0x01,每个单元的类型不同,具体取决于这些后面的第4个字节的值. 3个起始字节.一个NAL单元不是视频中的一个帧,每个帧由许多NAL单元组成.
好的.
我下载了random_youtube_video.mp4并从中删除了一帧:
ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.avi
得到了:
红色部分 - 这是AVI容器的一部分,其他 - 实际数据.正如你所看到的,我在这里00 00 24 A9而不是00 00 00 01
这个AVI文件播放完美
如您所见,这里完全相同的字节. 这个MP4文件播放完美
我试图删除原始数据:
ffmpeg -i pic.avi -c copy pic.h264

此文件无法在VLC中播放,甚至生成此文件的ffmpeg也无法解析它:

MP4Box 告诉我:
Cannot find H264 start code
Error importing pic.h264: BitStream Not Compliant
Run Code Online (Sandbox Code Playgroud)
当没有任何作用时,很难学习h264的内部结构.
所以,我有疑问:
更新:
这似乎是ffmpeg中的bug:
当我进行双重转换时: …
背景:
我一直在实施Vine这样的录像机,已有两天了。首先,我尝试了MediaRecorder。但是我需要的视频可能由小视频片段组成。此类不能用于录制短时视频剪辑。然后我找到了MediaCodec,FFmpeg和JavaCV。FFmpeg和JavaCV可以解决此问题。但是我必须使用许多库文件来编译我的项目。它将生成一个非常大的APK文件。所以我更喜欢通过MediaCodec实现它,尽管此类只能在Android 4.1之后使用。90%的用户将感到满意。
结果:
我终于得到了编码文件,但是无法播放。我通过FFprobe检查了信息,结果像:
输入0,h264,来自'test.mp4':持续时间:不适用,比特率:不适用流#0:0:视频:h264(基线),yuv420p,640x480,25 fps,25 tbr,1200k tbn, 50吨
我对H.264编码的机制了解不多。
码:
从此链接修改
public class AvcEncoder {
private static String TAG = AvcEncoder.class.getSimpleName();
private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;
private int mWidth, mHeight;
private byte[] mDestData;
public AvcEncoder(int w, int h) {
mWidth = w;
mHeight = h;
Log.d(TAG, "Thread Id: " + Thread.currentThread().getId());
File f = new File("/sdcard/videos/test.mp4");
try {
outputStream = new BufferedOutputStream(new FileOutputStream(f));
Log.i("AvcEncoder", "outputStream initialized");
} catch (Exception e) {
e.printStackTrace();
}
try { …Run Code Online (Sandbox Code Playgroud)