gpt4 book ai didi

ffmpeg - libav* 解码不正确

转载 作者:行者123 更新时间:2023-12-05 01:16:39 27 4
gpt4 key购买 nike

使用 libav 保存视频中的帧。

问题是,如果你多次调用 decode 函数,然后调用 2nd,然后就没有正确处理。

第一次这样的结论(一切正常):

[swscaler @ 0x8b48510]No accelerated colorspace conversion found from yuv420p to bgra.
good

第二个(找不到流,但它们是相同的):

[mp3 @ 0x8ae5800]Header missing
Last message repeated 223 times
[mp3 @ 0x8af31c0]Could not find codec parameters (Audio: mp1, 0 channels, s16)
[mp3 @ 0x8af31c0]Estimating duration from bitrate, this may be inaccurate
av_find_stream_info

请问哪里出错了

主要.cpp

avcodec_init();
avcodec_register_all();
av_register_all();
char *data;
int size;
//fill data and size
...
decode(data, size);
decode(data, size);

视频.cpp

int f_offset = 0;
int f_length = 0;
char *f_data = 0;

int64_t seekp(void *opaque, int64_t offset, int whence)
{
switch (whence)
{
case SEEK_SET:
if (offset > f_length || offset < 0)
return -1;
f_offset = offset;
return f_offset;
case SEEK_CUR:
if (f_offset + offset > f_length || f_offset + offset < 0)
return -1;
f_offset += offset;
return f_offset;
case SEEK_END:
if (offset > 0 || f_length + offset < 0)
return -1;
f_offset = f_length + offset;
return f_offset;
case AVSEEK_SIZE:
return f_length;
}

return -1;
}
int readp(void *opaque, uint8_t *buf, int buf_size)
{
if (f_offset == f_length)
return 0;

int length = buf_size <= (f_length - f_offset) ? buf_size : (f_length - f_offset);

memcpy(buf, f_data + f_offset, length);
f_offset += length;

return length;
}

bool decode(char *data, int length)
{
f_offset = 0;
f_length = length;
f_data = data;

int buffer_read_size = FF_MIN_BUFFER_SIZE;
uchar *buffer_read = (uchar *) av_mallocz(buffer_read_size + FF_INPUT_BUFFER_PADDING_SIZE);

AVProbeData pd;
pd.filename = "";
pd.buf_size = 4096 < f_length ? 4096 : f_length;
pd.buf = (uchar *) av_mallocz(pd.buf_size + AVPROBE_PADDING_SIZE);
memcpy(pd.buf, f_data, pd.buf_size);

AVInputFormat *pAVInputFormat = av_probe_input_format(&pd, 1);
if (pAVInputFormat == NULL)
{
std::cerr << "AVIF";
return false;
}
pAVInputFormat->flags |= AVFMT_NOFILE;

ByteIOContext ByteIOCtx;
if (init_put_byte(&ByteIOCtx, buffer_read, buffer_read_size, 0, NULL, readp, NULL, seekp) < 0)
{
std::cerr << "init_put_byte";
return false;
}

AVFormatContext *pFormatCtx;
if (av_open_input_stream(&pFormatCtx, &ByteIOCtx, "", pAVInputFormat, NULL) < 0)
{
std::cerr << "av_open_stream";
return false;
}

if (av_find_stream_info(pFormatCtx) < 0)
{
std::cerr << "av_find_stream_info";
return false;
}

int video_stream;
video_stream = -1;
for (uint i = 0; i < pFormatCtx->nb_streams; ++i)
if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
{
video_stream = i;
break;
}
if (video_stream == -1)
{
std::cerr << "video_stream == -1";
return false;
}

AVCodecContext *pCodecCtx;
pCodecCtx = pFormatCtx->streams[video_stream]->codec;

AVCodec *pCodec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
std::cerr << "pCodec == NULL";
return false;
}

if (avcodec_open(pCodecCtx, pCodec) < 0)
{
std::cerr << "avcodec_open";
return false;
}

AVFrame *pFrame;
pFrame = avcodec_alloc_frame();
if (pFrame == NULL)
{
std::cerr << "pFrame == NULL";
return false;
}
AVFrame *pFrameRGB;
pFrameRGB = avcodec_alloc_frame();
if (pFrameRGB == NULL)
{
std::cerr << "pFrameRGB == NULL";
return false;
}

int numBytes;
numBytes = avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);
uint8_t *buffer;
buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
if (buffer == NULL)
{
std::cerr << "buffer == NULL";
return false;
}

// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);

SwsContext *swsctx;
swsctx = sws_getContext(
pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB32,
SWS_BILINEAR, NULL, NULL, NULL);
if (swsctx == NULL)
{
std::cerr << "swsctx == NULL";
return false;
}

AVPacket packet;
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
if (packet.stream_index == video_stream)
{
int frame_finished;
avcodec_decode_video2(pCodecCtx, pFrame, &frame_finished, &packet);

if (frame_finished)
{
sws_scale(swsctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

std::cerr << "good";
av_close_input_stream(pFormatCtx);

return true;
}
else
std::cerr << "frame_finished == 0";
}
}

std::cerr << "av_read_frame < 0";
return false;
}

ffmpeg -版本

FFmpeg 0.6.2-4:0.6.2-1ubuntu1
libavutil 50.15. 1 / 50.15. 1
libavcodec 52.72. 2 / 52.72. 2
libavformat 52.64. 2 / 52.64. 2
libavdevice 52. 2. 0 / 52. 2. 0
libavfilter 1.19. 0 / 1.19. 0
libswscale 0.11. 0 / 0.11. 0
libpostproc 51. 2. 0 / 51. 2. 0

最佳答案

您可能已经阅读了一些 libav 教程并简单地复制/粘贴函数 decode() 中的几乎所有代码。真的错了。看来源。每次你想解码一些帧——不管是音频还是视频——你打开输入上下文,初始化编解码器和其他多次。每次你不关闭\释放它!请记住,即使您更正了 open\init 和 close\freeing 所有内容,每次调用 decode() 时都会得到相同的帧,因为这种方法会导致每次调用 decode 时都在文件开头寻找文件位置().

此外,您调用了 av_close_input_stream() 而不是 av_close_input_file(),您忘记了使用 avcodec_close() 关闭编解码器,使用 avpicture_free() 释放分配的图片,使用 av_free() 释放分配的帧,使用 av_free_packet() 释放读取的数据包( ).此外,您的函数 seekp() 和 readp() 也可能是错误的。

还有一个建议 - func sws_getContext() 现已弃用,您应该改用 sws_getCachedContext()。根据你的情况下的函数名称(多次调用 sws_getContext;但它仍然是错误的)它会工作得更快。

请再次阅读一些关于 libav 的教程。它们似乎都已过时,但您可以将其中已弃用或删除的功能替换为新功能,您可以在官方 libav doxygen 文档中找到这些功能。以下是一些链接:

http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
http://dranger.com/ffmpeg/ffmpeg.html

您将在 libav 的官方 API 文档中找到最新的示例。

http://libav.org/doxygen/master/examples.html

它们解释了最常见的用例。

关于ffmpeg - libav* 解码不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7140604/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com