ffmpeg 6.0 自定义 IO 错误:找不到流 0 的编解码器参数:未指定的像素格式

问题描述 投票:0回答:1

我运行ffmpeg 6.0源代码的avio_read_callback.c示例(ffmpeg-6.0/doc/examples/avio_read_callback.c),输入1080*1920p视频文件时出现错误信息:

./avio_read_callback 1080_1920.mp4
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1ec23c0] stream 0, offset 0x30: partial file
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1ec23c0] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none(tv, bt709), 1920x1080, 2179 kb/s): unspecified pixel format
Consider increasing the value for the 'analyzeduration' (10000000) and 'probesize' (10000000) options
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1080_1920.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.34.102
  Duration: 00:01:20.63, start: 0.000000, bitrate: N/A
  Stream #0:0[0x1](und): Video: h264 (avc1 / 0x31637661), none(tv, bt709), 1920x1080, 2179 kb/s, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 libx264

我尝试使用ffprobe获取视频信息,没问题:

ffprobe -i 1080_1920.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1080_1920.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.34.102
  Duration: 00:01:20.63, start: 0.000000, bitrate: 2182 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 2179 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
  Metadata:
    handler_name    : VideoHandler
    vendor_id       : [0][0][0][0]
    encoder         : Lavc59.37.100 libx264

然后我尝试使用avformat_open_input(&ctx, file_pash, NULL, NULL)直接打开这个视频文件,然后重新编译,重新运行这个例子,结果显示仍然可以:

./avio_read_callback 1080_1920.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1080_1920.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.34.102
  Duration: 00:01:20.63, start: 0.000000, bitrate: 2182 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 2179 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 libx264

我直接更改了打开文件的代码,如下所示:

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>

struct buffer_data {
    uint8_t *ptr;
    size_t size; ///< size left in the buffer
};

static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{
    struct buffer_data *bd = (struct buffer_data *)opaque;
    buf_size = FFMIN(buf_size, bd->size);

    if (!buf_size)
        return AVERROR_EOF;
    // printf("ptr:%p size:%zu\n", bd->ptr, bd->size);

    /* copy internal buffer data to buf */
    memcpy(buf, bd->ptr, buf_size);
    bd->ptr  += buf_size;
    bd->size -= buf_size;

    return buf_size;
}

int main(int argc, char *argv[])
{
    AVFormatContext *fmt_ctx = NULL;
    AVIOContext *avio_ctx = NULL;
    uint8_t *buffer = NULL, *avio_ctx_buffer = NULL;
    size_t buffer_size, avio_ctx_buffer_size = 4096;
    char *input_filename = NULL;
    int ret = 0;
    struct buffer_data bd = { 0 };

    if (argc != 2) {
        fprintf(stderr, "usage: %s input_file\n"
                "API example program to show how to read from a custom buffer "
                "accessed through AVIOContext.\n", argv[0]);
        return 1;
    }
    input_filename = argv[1];

    /* slurp file content into buffer */
    ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL);
    if (ret < 0)
        goto end;

    /* fill opaque structure used by the AVIOContext read callback */
    bd.ptr  = buffer;
    bd.size = buffer_size;

    /*
    if (!(fmt_ctx = avformat_alloc_context())) {
        ret = AVERROR(ENOMEM);
        goto end;
    }
    fmt_ctx->probesize = 100000000;
    fmt_ctx->max_analyze_duration = 0;

    avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
    if (!avio_ctx_buffer) {
        ret = AVERROR(ENOMEM);
        goto end;
    }
    avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,
                                  0, &bd, &read_packet, NULL, NULL);
    if (!avio_ctx) {
        ret = AVERROR(ENOMEM);
        goto end;
    }
    fmt_ctx->pb = avio_ctx;
    */

    ret = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open input\n");
        goto end;
    }

    ret = avformat_find_stream_info(fmt_ctx, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not find stream information\n");
        goto end;
    }

    av_dump_format(fmt_ctx, 0, input_filename, 0);

end:
    avformat_close_input(&fmt_ctx);

    /* note: the internal buffer could have changed, and be != avio_ctx_buffer */
    if (avio_ctx)
        av_freep(&avio_ctx->buffer);
    avio_context_free(&avio_ctx);

    av_file_unmap(buffer, buffer_size);

    if (ret < 0) {
        fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
        return 1;
    }

    return 0;
}

不知道为什么自定义会报错?

ffmpeg video-streaming
1个回答
0
投票

问题已通过阅读以下内容得到解决: 在此输入链接描述

并发布我的解决方案的内存 IO 查找功能:

struct buffer_data {
  uint8_t *ptr;
  uint8_t *ori_ptr;
  size_t size; ///< size left in the buffer
  size_t file_size;
};

static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{
    struct buffer_data *bd = (struct buffer_data *)opaque;
    buf_size = FFMIN(buf_size, bd->size);

    if (!buf_size)
        return AVERROR_EOF;
    // printf("ptr:%p size:%zu\n", bd->ptr, bd->size);

    /* copy internal buffer data to buf */
    memcpy(buf, bd->ptr, buf_size);
    bd->ptr  += buf_size;
    bd->size -= buf_size;

    return buf_size;
}

static int64_t seek(void *opaque, int64_t offset, int whence)
{
  struct buffer_data *bd = (struct buffer_data *)opaque;
  int64_t ret = -1;

  switch (whence) {
  case AVSEEK_SIZE:
    ret = bd->file_size;
    break;
  case SEEK_SET:
    bd->ptr = bd->ori_ptr + offset;
    bd->size = bd->file_size - offset;
    ret = offset;
    break;
  }
  return ret;
}

    avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,
                                  0, &bd, &read_packet, NULL, &seek);
© www.soinside.com 2019 - 2024. All rights reserved.