Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt 将AVFrame转换为RGB32时在sws_比例下崩溃_Qt_Ffmpeg_Android Ndk - Fatal编程技术网

Qt 将AVFrame转换为RGB32时在sws_比例下崩溃

Qt 将AVFrame转换为RGB32时在sws_比例下崩溃,qt,ffmpeg,android-ndk,Qt,Ffmpeg,Android Ndk,转换AV图片时在sws_比例下崩溃 起初,我使用sws_scale来实际放大帧,但是cpu开销太高,所以我决定只转换帧,并调整QImage的大小。在它工作之前,我在渲染时看到视频,但现在它在sws_级别崩溃 这是用Qt为Android编写的,并使用FFMpeg 3.1.4 另外,是否有其他方法可以避免使用不推荐使用的函数 有人知道我为什么会在sws_级别上崩溃吗 视频帧复制的类 class VideoFrameCopy { public: VideoFrameCopy() {}

转换AV图片时在sws_比例下崩溃

起初,我使用sws_scale来实际放大帧,但是cpu开销太高,所以我决定只转换帧,并调整QImage的大小。在它工作之前,我在渲染时看到视频,但现在它在sws_级别崩溃

这是用Qt为Android编写的,并使用FFMpeg 3.1.4

另外,是否有其他方法可以避免使用不推荐使用的函数

有人知道我为什么会在sws_级别上崩溃吗

视频帧复制的类

class VideoFrameCopy {
public:
    VideoFrameCopy() {}
    VideoFrameCopy(AVFrame *frame) { copyAVFrame(frame); }
    ~VideoFrameCopy();
    void copyAVFrame(AVFrame *frame); // copy essential data from AVFrame

    AVPicture picture;

    int64_t pkt_pts = -1; // show it hasn't been initialised
    int64_t best_pts;
    int interlaced_frame;
    int width = 0, height = 0;
    int format = -1;
};
将帧转换为RGBA8888 QImage的代码

if (frame) {

    if (image->width() != vid_ctx->width || image->height() != vid_ctx->height) {
        QSize old_size(image->size());

        // block until renderer has finished with it

        while (parent->buffer_ready) {
            QThread::yieldCurrentThread();
        }

        delete image;

        image = new QImage(vid_ctx->width, vid_ctx->height, QImage::Format_RGBA8888);
        parent->image = image;

        if (scale_context) sws_freeContext(scale_context);
        scale_context = nullptr;

        qDebug() << "Video image size" << image->size() << "old" << old_size;
    }

    // the src width and height may need to change to use the context info instead

    if (!scale_context) { // create the scale context
        int src_width = vid_ctx->width;
        int src_height = vid_ctx->height;
        AVPixelFormat src_format = vid_ctx->pix_fmt;//(AVPixelFormat)frame->format;

        int dst_width = vid_ctx->width;
        int dst_height = vid_ctx->height;
        AVPixelFormat dst_format = AV_PIX_FMT_RGBA;

        scale_context = sws_getContext(src_width, src_height, src_format,
                                       dst_width, dst_height, dst_format,
                                       SWS_FAST_BILINEAR, NULL, NULL, NULL);

        av_image_fill_linesizes(scale_linesizes, dst_format, vid_ctx->width);

        qDebug() << "Created scale context" << scale_context;
    }

    if (scale_context) { // valid
        scale_data[0] = image->bits();

        sws_scale(scale_context,
                  frame->picture.data, // deprecated
                  frame->picture.linesize, // deprecated
                  0, image->height(),
                  scale_data,
                  scale_linesizes);

        qDebug() << "Frame converted";
    }

    //av_frame_unref(frame);

    //vid_frames_mutex.lock();
    //if (quit) av_frame_free(&frame);
    if (quit) delete frame;
    else vid_frames_unused.push_back(frame);
    //vid_frames_mutex.unlock();

    //qDebug() << "got frame" << clock_current_frame_last << "clock" << clock_current_time;
}

vid_frames_mutex.unlock();

return frame != nullptr;
if(帧){
如果(图像->宽度()!=vid|ctx->宽度|图像->高度()!=vid|ctx->高度){
QSize旧尺寸(图像->尺寸());
//块,直到渲染器完成
while(父级->缓冲区准备就绪){
QThread::yieldCurrentThread();
}
删除图像;
图像=新QImage(vid_ctx->宽度,vid_ctx->高度,QImage::Format_RGBA888);
父->图像=图像;
if(缩放上下文)sws(缩放上下文);
scale_context=nullptr;
qDebug()pix_fmt;//(AVPixelFormat)帧->格式;
int dst_width=vid_ctx->width;
int dst_height=vid_ctx->height;
AVPixelFormat dst_format=AV_PIX_FMT_RGBA;
scale_context=sws_getContext(src_宽度、src_高度、src_格式、,
dst_宽度、dst_高度、dst_格式、,
SWS_快速_双线性,零,零,零);
av图像填充线尺寸(缩放线尺寸、dst格式、视频ctx->宽度);
qDebug()picture.data,//已弃用
frame->picture.linesize,//已弃用
0,图像->高度(),
比例尺数据,
刻度线尺寸);
qDebug()高度;
格式=帧->格式;
隔行扫描帧=帧->隔行扫描帧;
如果(pkt_pts==-1){//alloc picture
if(avpicture\u alloc(&picture,(AVPixelFormat)格式、宽度、高度)<0)返回;//已弃用
int size=avpicture\u get\u size((AVPixelFormat)格式、宽度、高度);//已弃用
uint8\u t*图片数据=(uint8\u t*)av\u malloc(大小);
avpicture_填充(&picture,picture_数据,(AVPixelFormat)格式、宽度、高度);//已弃用

qDebug()关于崩溃:了解访问冲突是否与读取输入图片或写入输出图片有关会很有帮助。无论如何,到目前为止,我只能看到代码中的一个问题:当使用QImage作为目标时,不能使用
av_image\u fill_linesize
。linesize必须与实际的图像布局匹配(就像数据指针必须匹配内存中的实际图像位置一样)因此请使用以下方法:

scale_linesizes[0] = image->bytesPerLine();

关于所有不推荐使用的功能:您不应该永远使用AVPicture。
AVFrame
可以完成AVPicture所能做的一切,然后是一些。例如,如果您有一个“正常”的AVFrame(例如,来自FFmpeg的解码器)如果你想保留一个副本,可以使用
av_frame\u ref
av_frame\u copy
。这将分配内存并复制图片,或者如果可能的话,它将只共享图片缓冲区。如果你自己填写了AVFrame,那么相同的函数调用应该同样有效(假设你没有填写frame->buf[]如果你有一个帧,并且你想得到你自己的“私有/非共享拷贝,你可以使用
av\u frame\u make\u writable
,它会制作一个拷贝(如果需要的话)。最后,如果你想无条件拷贝图片数据(你不必,但如果出于某种原因你需要),然后做
av\u frame\u alloc
av\u frame\u copy\u props
,填充宽度/高度/格式字段,
av\u frame\u get\u buffer
,最后做
av\u frame\u copy

,关于崩溃:了解访问冲突是否与读取输入图片或写入输出图片有关将很有帮助。无论如何,到目前为止,我能做到代码中只有一个问题:当使用QImage作为目标时,不能使用
av_image\u fill\u linesize
。linesize必须与实际图像布局匹配(就像数据指针必须与内存中的实际图像位置匹配一样),因此请使用以下方法:

scale_linesizes[0] = image->bytesPerLine();

关于所有不推荐使用的功能:您不应该永远使用AVPicture。
AVFrame
可以完成AVPicture所能做的一切,然后是一些。例如,如果您有一个“正常”的AVFrame(例如,来自FFmpeg的解码器)如果你想保留一个副本,可以使用
av_frame\u ref
av_frame\u copy
。这将分配内存并复制图片,或者如果可能的话,它将只共享图片缓冲区。如果你自己填写了AVFrame,那么相同的函数调用应该同样有效(假设你没有填写frame->buf[]如果你有一个帧,并且你想得到你自己的“私有/非共享拷贝,你可以使用
av\u frame\u make\u writable
,它会制作一个拷贝(如果需要的话)。最后,如果你想无条件拷贝图片数据(你不必,但如果出于某种原因你需要),然后做
av\u frame\u alloc
av\u frame\u copy\u props
,填充宽度/高度/格式字段,
av\u frame\u get\u buffer
,最后做
av\u frame\u copy

是的。非常感谢您的解释。这解决了我遇到的很多问题,特别是复制图片数据的顺序。我已经做了一些重要的工作我无法更改代码,主要是取消缩放,只是将图像转换为RGBA,并使用未弃用的API调用。这个答案将作为我的参考。关于崩溃,我仍然无法确定这一点,尽管这可能是AVFrame中的错误设置,正如您所提到的,设置帧副本..是的。谢谢解释到此为止。这已经解决了我遇到的很多问题,特别是复制文件的顺序
scale_linesizes[0] = image->bytesPerLine();