Javacv:解码H.264"生活"流从Android设备RED5服务器来临 [英] Javacv: Decoding H.264 "live" stream coming from red5 server on android device

查看:1203
本文介绍了Javacv:解码H.264"生活"流从Android设备RED5服务器来临的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的问题, 我实现了一个服务器端应用程序中使用的Red5,它发送H.264连接codeD实况流,在流被接收为byte []的
客户端 为了解除code它在Android客户端我按照 Javacv-FFmpeg的库。在code解码如下:

Here is my problem, I have implemented a server side application using Red5, which sends H.264 encoded live stream, on client side the stream is received as byte[]
In order to decode it on Android client side i have followed the Javacv-FFmpeg library. The code for decoding is as follows

public Frame decodeVideo(byte[] data,long timestamp){
           frame.image = null;
           frame.samples = null;
           avcodec.av_init_packet(pkt);
           BytePointer video_data = new BytePointer(data);
           avcodec.AVCodec codec = avcodec.avcodec_find_decoder(codec_id);
           video_c = null;
           video_c = avcodec.avcodec_alloc_context3(codec);
           video_c.width(320);
           video_c.height(240);
           video_c.pix_fmt(0);
           video_c.flags2(video_c.flags2()|avcodec.CODEC_FLAG2_CHUNKS);
           avcodec.avcodec_open2(video_c, codec, null))
           picture = avcodec.avcodec_alloc_frame()
           pkt.data(video_data);
           pkt.size(data.length);
           int len = avcodec.avcodec_decode_video2(video_c, picture, got_frame, pkt);
           if ((len >= 0) && ( got_frame[0] != 0)) {
             ....
              process the decoded frame into **IPLImage of Javacv** and render it with **Imageview** of Android
           }
} 

从服务器接收到的数据如下
几帧有以下模式
17 01 00 00 00 00 00 00 02 09 10 00 00 00 0F 06 00 01 C0 01 07 09 08 04 9A 00 00 03 00 80 00 00 16 EF 65 88 80 07 00 05 6C 98 90 00 ...

Data received from server is as follows
Few Frames having following pattern
17 01 00 00 00 00 00 00 02 09 10 00 00 00 0F 06 00 01 C0 01 07 09 08 04 9A 00 00 03 00 80 00 00 16 EF 65 88 80 07 00 05 6C 98 90 00...

有以下模式
许多帧 27 01 00 00 00 00 00 00 02 09 30 00 00 00 0C 06 01 07 09 08 05 9A 00 00 03 00 80 00 00 0D 77 41 9A 02 04 15 B5 06 20 E3 11 E2 3C 46 ...

Many frames having following pattern
27 01 00 00 00 00 00 00 02 09 30 00 00 00 0C 06 01 07 09 08 05 9A 00 00 03 00 80 00 00 0D 77 41 9A 02 04 15 B5 06 20 E3 11 E2 3C 46 ....

使用H.264 codeC的去codeR,德codeR输出长度> 0,但got_frames = 0始终。
随着MPEG1 codeC,德codeR输出长度> 0和got_frames> 0,但输出图像为绿色或失真。

With H.264 codec for decoder, decoder outputs length >0 but got_frames=0 always.
With MPEG1 codec, decoder outputs length >0 and got_frames>0 but the output image is green or distorted.

但是以下javacv我可以去$ C C的本地文件(H.264连接codeD)与上文类似code $的FFmpegFrameGrabber code。

However following FFmpegFrameGrabber code of javacv i can decode the local files( H.264 encoded ) with similar code as above.

我不知道什么细节我很想念,和标题相关数据操作或设定codeC适合去codeR。

I wonder what details i am missing, and header related data manipulation or setting codec appropriate for decoder.

任何建议,帮助AP preciated。
先谢谢了。

Any suggestion, help appreciated.
Thanks in advance.

推荐答案

Atlast ......终于到大量的RND后工作。
我所缺少的是alalyze视频帧结构。视频是由I,P帧..的我的帧是帧信息,其中存储有关下一后续帧的信息。 P帧是相框,其中包含实际的视频帧...
所以我需要去code中的P帧I帧WRT信息.. 因此,最终code是东西如下:

Atlast... finally got to working after lots of RnD.
What i am missing is alalyze the video frame structure. Video is made up of "I" , "P" frames.. "I" frame is information frame, which stores the information about next subsequent frames. "P" frame is picture frame, which holds actual video frame...
So i need to decode the "P" frames w.r.t information in "I" frame.. So the final code is something as follows

public IplImage decodeFromVideo(byte[] data, long timeStamp) {
avcodec.av_init_packet(reveivedVideoPacket); // Empty AVPacket
/*
 * Determine if the frame is a Data Frame or Key. IFrame 1 = PFrame 0 = Key
 * Frame
 */
byte frameFlag = data[1];
byte[] subData = Arrays.copyOfRange(data, 5, data.length);

BytePointer videoData = new BytePointer(subData);
if (frameFlag == 0) {
    avcodec.AVCodec codec = avcodec
            .avcodec_find_decoder(avcodec.AV_CODEC_ID_H264);
    if (codec != null) {
        videoCodecContext = null;
        videoCodecContext = avcodec.avcodec_alloc_context3(codec);
        videoCodecContext.width(320);
        videoCodecContext.height(240);
        videoCodecContext.pix_fmt(avutil.AV_PIX_FMT_YUV420P);
        videoCodecContext.codec_type(avutil.AVMEDIA_TYPE_VIDEO);
        videoCodecContext.extradata(videoData);
        videoCodecContext.extradata_size(videoData.capacity());

        videoCodecContext.flags2(videoCodecContext.flags2()
                | avcodec.CODEC_FLAG2_CHUNKS);
        avcodec.avcodec_open2(videoCodecContext, codec,
                (PointerPointer) null);

        if ((videoCodecContext.time_base().num() > 1000)
                && (videoCodecContext.time_base().den() == 1)) {
            videoCodecContext.time_base().den(1000);
        }
    } else {
        Log.e("test", "Codec could not be opened");
    }
}

if ((decodedPicture = avcodec.avcodec_alloc_frame()) != null) {
    if ((processedPicture = avcodec.avcodec_alloc_frame()) != null) {
        int width = getImageWidth() > 0 ? getImageWidth()
                : videoCodecContext.width();
        int height = getImageHeight() > 0 ? getImageHeight()
                : videoCodecContext.height();

        switch (imageMode) {
        case COLOR:
        case GRAY:
            int fmt = 3;
            int size = avcodec.avpicture_get_size(fmt, width, height);
            processPictureBuffer = new BytePointer(
                    avutil.av_malloc(size));
            avcodec.avpicture_fill(new AVPicture(processedPicture),
                    processPictureBuffer, fmt, width, height);
            returnImageFrame = opencv_core.IplImage.createHeader(320,
                    240, 8, 1);
            break;
        case RAW:
            processPictureBuffer = null;
            returnImageFrame = opencv_core.IplImage.createHeader(320,
                    240, 8, 1);
            break;
        default:
            Log.d("showit",
                    "At default of swith case 1.$SwitchMap$com$googlecode$javacv$FrameGrabber$ImageMode[ imageMode.ordinal()]");
        }

        reveivedVideoPacket.data(videoData);
        reveivedVideoPacket.size(videoData.capacity());

        reveivedVideoPacket.pts(timeStamp);
        videoCodecContext.pix_fmt(avutil.AV_PIX_FMT_YUV420P);
        decodedFrameLength = avcodec.avcodec_decode_video2(videoCodecContext,
                decodedPicture, isVideoDecoded, reveivedVideoPacket);

if ((decodedFrameLength >= 0) && (isVideoDecoded[0] != 0)) {
 .... Process image same as javacv .....
}

希望它西港岛线帮助别人。

Hope it wil help others..

这篇关于Javacv:解码H.264"生活"流从Android设备RED5服务器来临的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆