使用ffmpeg仅写入视频(无音频)文件。 av_write_header失败

时间:2018-01-19 11:46:48

标签: ffmpeg

我有带有VP8编码数据的RTP数据包。我想将它写入mkv文件或webm文件。我尝试了一下,但我还没有成功。我的代码如下

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>

#include <libavutil/avassert.h>
#include <libavutil/channel_layout.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>

bool mfmedia_init_ffmpeg();
void mfmedia_ffprint(void *handle, int cnt, const char *format, va_list valist);

int main()
{
    mfmedia_init_ffmpeg();
    return 0;
}

bool mfmedia_init_ffmpeg() 
{
    bool ret = false;

    AVCodecContext* context;
    AVCodec* codec;
    AVFormatContext* format;
    AVStream* stream;

    unsigned fps = 24;
    unsigned width = 768;
    unsigned height = 608;

    av_register_all();

    int err = 0;
    char errorLog[128] = { 0 };

    av_log_set_level(AV_LOG_TRACE);
    av_log_set_callback(mfmedia_ffprint);

    err = avformat_alloc_output_context2(&format, NULL, NULL, "o.webm");
    if (err < 0) 
    {
        printf("Cannot allocate output context: %s\n", av_make_error_string(errorLog, 128, err));
        goto last;
    }

    codec = avcodec_find_encoder(AV_CODEC_ID_VP8);
    if (!codec) 
    {
        printf("Cannot find an encoder\n");
        goto last;
    }

    context = avcodec_alloc_context3(codec);
    if (!context) 
    {
        printf("Cannot allocate a codec context\n");
        goto last;
    }

    context->pix_fmt = AV_PIX_FMT_YUV420P;
    context->width = width;
    context->height = height;
    context->time_base = (AVRational){1, fps};

    err = avcodec_open2(context, codec, NULL);
    if(err < 0) 
    {
        printf("Cannot open codec: %s\n", av_make_error_string(errorLog, 128, err));
        goto last;
    }

    stream = avformat_new_stream(format, codec);
    if (!stream) 
    {
        printf("Cannot create a new stream\n");
        goto last;
    }

    //av_dump_format(format, 0, "o.webm", 1);

    err = avio_open(&format->pb, "o.webm", AVIO_FLAG_WRITE);
    if(err < 0) 
    {
        printf("Cannot open output: %s\n", av_make_error_string(errorLog, 128, err));
        goto last;
    }

    err = avformat_write_header(format, NULL); 
    if(err < 0) 
    {
        printf("Cannot write header to stream: %s\n", av_make_error_string(errorLog, 128, err));
        goto last;
    }
    ret = true;

last:
    return ret;
}

void mfmedia_ffprint(void *handle, int cnt, const char *format, va_list valist)
{
    char *log_buf = (char *)malloc(38192);
    int length;

    if(log_buf)
    {
        time_t rawtime;
        time ( &rawtime );

        length = vsprintf(log_buf ,format, valist);
        length += sprintf((log_buf + length), " : %s ", ctime (&rawtime));
        *(log_buf + length) = 0x0;

        printf("%s", log_buf);
        fflush(stdout);
        free(log_buf);
    }
}

当我调用avformat_write_header时失败。

从跟踪日志(到结尾),我看到了

设置默认白名单'文件,加密'  :1月19日星期五16:58:57 2018年  不推荐使用AVStream.codec将编解码器参数传递给多路复用器,而是使用AVStream.codecpar。  :1月19日星期五16:58:57 2018年  尺寸未设定  :1月19日星期五16:58:57 2018年  无法将标题写入流:无效的参数

请告诉我为什么avformat_write_header失败。

1 个答案:

答案 0 :(得分:1)

这应该可行,请在//av_dump_format(format, 0, "o.webm", 1);

的正上方输入此代码
/* copy the stream parameters to the muxer */
err = avcodec_parameters_from_context(stream->codecpar, context);
if (err < 0) {
    fprintf(stderr, "Could not copy the stream parameters\n");
    exit(1);
}