首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >mpeg2 ts android ffmpeg openmax

mpeg2 ts android ffmpeg openmax
EN

Stack Overflow用户
提问于 2014-06-13 10:47:26
回答 1查看 730关注 0票数 1

设置如下:

  1. 组播服务器1000 UDP,UDP,Mpeg2 2-TS第1部分(H.222)流媒体直播电视频道。
  2. 四核1.5Ghz Android 4.2.2 GLES 2.0渲染器。
  3. FFMpeg库
  4. Eclipse开普勒,Android /NDK等,运行在Windows8.1上。
  5. 输出屏幕1920 x 1080,我使用的纹理为2048x1024,每秒35到45帧。

应用程序:

  1. 渲染器线程连续运行,当媒体图像准备就绪时,通过将片段上传到gpu来更新单个纹理。
  2. 媒体处理程序线程,从服务器/或本地存储下载和处理媒体。
  3. 视频线程,一个用于缓冲UDP分组,另一个用于将分组解码成帧。

我正在将ffmpeg连接到UDP流,并且数据包正在被缓冲,并且看起来很好地解码。数据包缓冲器是充足的,没有低于/超过流。我面临的问题是,它似乎是切分帧(即只回放在每这么多帧中的一个)。我知道我需要区分I/P/B帧,但是现在,举起手来,我没有头绪。我甚至尝试过一次黑客攻击来检测我的帧,但没有结果。此外,我只是渲染的框架不到四分之一的屏幕。所以我不使用全屏解码。

解码后的帧也存储在单独的缓冲器中,以裁剪页撕裂。缓冲区的数量我也改变了,从1到10,没有运气。

根据我对OpenMax IL的发现,它只处理MPeg2 2-TS第3部分(H.264和AAC),但是您可以使用自己的解码器。我知道您可以在其中添加自己的解码组件。我尝试这条路值得吗?还是我应该继续走下去?

帧解码器(只有渲染器在准备就绪时才会转换和缩放帧) /* *此功能将在数据包中运行,并继续解码*直到帧首先准备就绪,或者是帧之外的数据包*/

代码语言:javascript
运行
复制
while (packetsUsed[decCurrent])
{
    hack_for_i_frame:
    i = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packets[decCurrent]);
    packetsUsed[decCurrent] = 0; // finished with this one
    i = packets[decCurrent].flags & 0x0001;
    decCurrent++;
    if (decCurrent >= MAXPACKETS) decCurrent = 0;
    if (frameFinished)
    {
        ready_pFrame = pFrame;
        frameReady = true;  // notify renderer
        frameCounter++;
        if (frameCounter>=MAXFRAMES) frameCounter = 0;
        pFrame = pFrames[frameCounter];
        return 0;
    }
    else if (i)
        goto hack_for_i_frame;
}

return 0;

包读取器(以p线程形式产生) void *mainPacketReader(Voidptr){ int res;

代码语言:javascript
运行
复制
while ( threadState == TS_RUNNING )
{
    if (packetsUsed[prCurrent])
    {
        LOGE("Packet buffer overflow, dropping packet...");
        av_read_frame( pFormatCtx, &packet );
    }
    else if ( av_read_frame( pFormatCtx, &packets[prCurrent] ) >= 0 )
    {
        if ( packets[prCurrent].stream_index == videoStream )
        {
            packetsUsed[prCurrent] = 1; // flag as used
            prCurrent++;
            if ( prCurrent >= MAXPACKETS )
            {
                prCurrent = 0;
            }
        }

        // here check if the packet is audio and add to audio buffer
    }
}
return NULL;

而渲染器只是简单地在调用这个函数之前已经绑定了这个//纹理

代码语言:javascript
运行
复制
if ( frameReady == false ) return;

AVFrame *temp;  // set to frame 'not' currently being decoded
temp = ready_pFrame;

sws_scale(sws_ctx,(uint8_t const* const *)temp->data,
        temp->linesize, 0, pCodecCtx->height,
        pFrameRGB->data, pFrameRGB->linesize);

glTexSubImage2D(GL_TEXTURE_2D, 0,
        XPOS, YPOS, WID, HGT,
        GL_RGBA, GL_UNSIGNED_BYTE, buffer);

frameReady = false;

在过去,libvlc也有音频同步问题,所以这是我决定使用ffmpeg和做所有的驴子工作从零。

如果有人有任何关于如何停止视频播放(在VLC播放器中工作很好)或可能的另一条路线下降的指示,这将是非常感谢的。

编辑我删除了i帧的黑客(完全无用)。将sws_scale函数从呈现器移动到分组解码器。我把udp数据包读取器线程放在一边。

同时,我还将分组读取器线程和分组解码器线程的优先级更改为实时。从那以后,我就不会有很多丢包了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-10 11:33:38

(在最终确定答案按钮在哪里之后)

I帧黑客是完全无用的,为了保存渲染器中的线程过载,sws_scale被移动到解码器线程中。

我还通过完全摆脱sws_scale,将每个YUV帧上传到gpu,并使用片段着色器转换为rgb,从而实现了这一点。

任何对将YUV转换为RGB的着色器感兴趣的人在这里是非常简单的:

顶点着色机

代码语言:javascript
运行
复制
attribute vec4 qt_Vertex;
attribute vec2 qt_InUVCoords;
attribute vec4 qt_InColor;
uniform mat4 qt_OrthoMatrix;

varying vec2 qt_TexCoord0;
varying vec4 qt_OutColor;

void main(void)
{
    gl_Position = qt_OrthoMatrix * qt_Vertex;
    qt_TexCoord0 = qt_InUVCoords;
    qt_OutColor = qt_InColor;
}

碎片着色器:

代码语言:javascript
运行
复制
precision mediump float;

uniform sampler2D qt_TextureY;
uniform sampler2D qt_TextureU;
uniform sampler2D qt_TextureV;

varying vec4 qt_OutColor;

varying vec2 qt_TexCoord0;

const float num1 = 1.403;   // line 1

const float num2 = 0.344;   // line 2
const float num3 = 0.714;

const float num4 = 1.770;   // line 3
const float num5 = 1.0;

const float half1 = 0.5;

void main(void)
{
    float y = texture2D(qt_TextureY, qt_TexCoord0).r;
    float u = texture2D(qt_TextureU, qt_TexCoord0).r - half1;
    float v = texture2D(qt_TextureV, qt_TexCoord0).r - half1;

    gl_FragColor = vec4( y + num1 * v,
                         y - num2 * u - num3 * v,
                         y + num4 * u, num5) * qt_OutColor;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24203529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档