解码H264流最终失败

时间:2016-06-15 15:31:00

标签: c++ qt libavcodec libav libavformat

在我的c ++ / Qt项目中尝试使用我的覆盆子pi(armv7)上的libav连接到我的家庭中央电视台几周后,我能够正确显示我的相机一段时间(至少20分钟)几乎没有任何NAL控制台中的警告(但有关无效NAL单元的警告)。但是,最终我只是开始在控制台中看到一个灰色的屏幕和许多NAL警告,我必须关闭并重新打开连接才能正确显示我的相机。我已多次搜索互联网,以确保我正确理解av_parser_parse2,我想我是。

我已经粘贴了下面的3个主要功能,希望有人能告诉我 - 使用libav解码h264流是否比我目前理解的更多?

谢谢。

void MainWindow::playStreamToScreen(MainWindow* app)
{

avcodec_register_all();

codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
    qDebug() << "codec not found\n";
    return;
}

c = avcodec_alloc_context3(codec);
/* if(codec->capabilities & CODEC_CAP_TRUNCATED)
    c->flags |= CODEC_FLAG_TRUNCATED;
if(codec->capabilities & CODEC_FLAG2_CHUNKS)
    c->flags |= CODEC_FLAG2_CHUNKS;*//* We may send incomplete frames */
picture = av_frame_alloc();
pFrameRGB=av_frame_alloc();
int  numBytes=avpicture_get_size(pix_fmt_dst, myWidth, myHeight);
buffer= (uint8_t*)malloc(numBytes);
if(avpicture_fill((AVPicture *)pFrameRGB, buffer, pix_fmt_dst,
                  myWidth, myHeight) < 0)
{
    qDebug() << "failed fill picture";
}
if (avcodec_open2(c, codec, NULL) < 0) {
    qDebug() << "could not open codec\n";
    return;
}

frame = 0;

if(parser == NULL)parser = av_parser_init(AV_CODEC_ID_H264);
if(parser == NULL)
{
    qDebug() << "after init parser is null";
    return;
}
parser->flags |= PARSER_FLAG_ONCE;

struct timeval t;
float inv_fps2;// = 4;
int ii = 0;
inv_fps2 = 1e6/9.98;//av_q2d(c->time_base);
qDebug() << "before timebase";
c->time_base = (AVRational){1,10};
c->bit_rate =  251000;
c->width = 352;
c->height = 288;
c->pix_fmt = AV_PIX_FMT_YUV420P;

if(img_convert_ctx == NULL)
{

    img_convert_ctx = sws_getCachedContext ( img_convert_ctx, c->width, c->height,
                                             AV_PIX_FMT_YUV420P, myWidth, myHeight,  AV_PIX_FMT_RGB555,
                                             SWS_LANCZOS | SWS_ACCURATE_RND , NULL, NULL, NULL );
}

running = true;
int retval;
gettimeofday(&t, 0);


}


void MainWindow::display_frame(AVCodecContext* cc, AVFrame *frame, SwsContext* img_convert_ctx, MainWindow* app)
{

sws_scale ( img_convert_ctx, frame->data, frame->linesize, 0,
            288, pFrameRGB->data, pFrameRGB->linesize );

app->currentImage = QImage(pFrameRGB->data[0], app->myWidth, app->myHeight, pFrameRGB->linesize[0], QImage::Format_RGB555) .copy();// - See more at: http://www.mzan.com/article/30784549-best-simplest-way-to-display-ffmpeg-frames-in-qt5-solved.shtml#sthash.RvAFLQsc.dpuf
QImage img2 = app->currentImage.scaled(app->width(), app->height(), Qt::KeepAspectRatio);
QMetaObject::invokeMethod(app->myLabel, "setImage", Qt::QueuedConnection, Q_ARG(QImage, img2));
app->myLabel->setFixedSize(app->width(), app->height());


}


void MainWindow::socketReadyRead()
{
    if(connectingToLive && i  == 0)
    {
    qDebug() << "starting live stream";
    i++;
    this->playStreamToScreen(this);

    }
    else if(connectingToLive && i > 0)
    {
    QByteArray temp;
    int inbuf_start = 0;
    int inbuf_len = 0;

    temp.append(socket->readAll());//reads from network here



    inbuf_len = temp.size();
    inbuf_start = 0;

    int out_size;

    while (inbuf_len)
    {
        av_init_packet(&packet2);
        packet2.data = 0;
        packet2.size = 0;
        len = av_parser_parse2(parser, c, &packet2.data, &packet2.size,
                               (uint8_t*)temp.constData()+ inbuf_start, inbuf_len,
                               AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);

        inbuf_start += len;
        inbuf_len -= len;

        if(packet2.size == 0 && len >= 0)
        {


            break;

        }

        else if(len)
        {

            retval = avcodec_decode_video2(c, picture, &got_picture, &packet2);

            if (got_picture && retval > 0)
            {
                display_frame(c, picture, img_convert_ctx, this);

            }

        }

    }


}

}

0 个答案:

没有答案