shang_cm
shang_cm
采纳率0%
2019-08-19 10:12 浏览 384

ffmpeg4通过调用SDK,给视频添加水印封装出来的视频只有声音,图像为黑屏。求各位大神给分析分析。

希望实现的是对任意的视频文件添加水印,等同于命令行

ffmpeg -i D:\mmRun.mp4 -vf drawtext=fontfile=text=welcome D:\mmRun_Water.mp4

然而由于本人对ffmpeg了解不深,始终无法达到想要的效果,请各位大侠帮忙看看究竟是哪里出了问题。
当前共有两个问题

  1. 视频保存出来有声音,但是画面为黑屏?
  2. 输入进入的原视频问题为24M,为何保存出来的目标视频文件足足有330M?

#include <windows.h>
#include <tchar.h>


extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/buffersink.h>
#include <libavutil/opt.h>
}
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "avutil.lib")

AVFormatContext* pInputFormatCtx = NULL;
AVCodecContext* pInputEncContext = NULL;
AVCodec* pInputCodec = NULL;
int iVideoStream = 0;

AVPacket packetinput = { 0 };
AVPacket packetoutput = { 0 };
AVFrame* frameinput = NULL;
AVFrame* framefilt = NULL;

AVFilterGraph* filtGraph = NULL;
AVFilterContext* filtBufferSrcCtx = NULL;
AVFilterContext* filtBufferSinkCtx = NULL;


AVFormatContext* pOutputFormatCtx = NULL;
AVCodec* pOutCodec = NULL;
AVCodecContext* pOutputEncContext = NULL;
AVStream** out_streams = NULL;

const char* szInputFileName = "D:\\mmRun.mp4";
const char* szOutputFileName = "D:\\mmRun_water.mp4";

int InitFilter()
{
    int iError = 0;
    char argsfilter[512] = { 0 };
    snprintf(argsfilter, _countof(argsfilter),
        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
        pInputEncContext->width, pInputEncContext->height, pInputEncContext->pix_fmt,
        pInputFormatCtx->streams[iVideoStream]->time_base.num, pInputFormatCtx->streams[iVideoStream]->time_base.den,
        pInputEncContext->sample_aspect_ratio.num, pInputEncContext->sample_aspect_ratio.den);

    const AVFilter* filtbuffer = avfilter_get_by_name("buffer");
    const AVFilter* filtbuffersink = avfilter_get_by_name("buffersink");
    AVFilterInOut* filtoutputs = avfilter_inout_alloc();
    AVFilterInOut* filtinputs = avfilter_inout_alloc();

    filtGraph = avfilter_graph_alloc();
    if (NULL == filtGraph)
    {
        goto FUN_CLEAN;
    }

    iError = avfilter_graph_create_filter(&filtBufferSrcCtx, filtbuffer, "in", argsfilter, NULL, filtGraph);
    if (0 > iError)
    {
        goto FUN_CLEAN;
    }

    iError = avfilter_graph_create_filter(&filtBufferSinkCtx, filtbuffersink, "out", NULL, NULL, filtGraph);
    if (0 > iError)
    {
        goto FUN_CLEAN;
    }

    filtoutputs->name = av_strdup("in");
    filtoutputs->filter_ctx = filtBufferSrcCtx;
    filtoutputs->pad_idx = 0;
    filtoutputs->next = NULL;


    filtinputs->name = av_strdup("out");
    filtinputs->filter_ctx = filtBufferSinkCtx;
    filtinputs->pad_idx = 0;
    filtinputs->next = NULL;

    iError = avfilter_graph_parse_ptr(filtGraph, "drawtext=text=welcome output", &filtinputs, &filtoutputs, NULL);
    if (0 > iError)
    {
        goto FUN_CLEAN;
    }

    iError = avfilter_graph_config(filtGraph, NULL);
    if (0 > iError)
    {
        goto FUN_CLEAN;
    }

    avfilter_inout_free(&filtoutputs);
    avfilter_inout_free(&filtinputs);
    return iError;

FUN_CLEAN:
    if (NULL != filtGraph)
    {
        avfilter_graph_free(&filtGraph);
        filtGraph = NULL;
    }

    if (NULL != filtoutputs)
    {
        avfilter_inout_free(&filtoutputs);
        filtoutputs = NULL;
    }

    if (NULL != filtinputs)
    {
        avfilter_inout_free(&filtinputs);
        filtinputs = NULL;
    }

    filtBufferSrcCtx = NULL;
    filtBufferSinkCtx = NULL;

    return -1;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int iError = 0;

    //打开输入文件开始
    iError = avformat_open_input(&pInputFormatCtx, szInputFileName, NULL, NULL);
    if (0 != iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    iError = avformat_find_stream_info(pInputFormatCtx, NULL);
    if (0 > iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    iVideoStream = av_find_best_stream(pInputFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pInputCodec, 0);
    if (0 > iVideoStream)
    {
        goto FUN_CLEANUP_INPUT;
    }

    pInputEncContext = avcodec_alloc_context3(pInputCodec);
    iError = avcodec_parameters_to_context(pInputEncContext, pInputFormatCtx->streams[iVideoStream]->codecpar);
    if (0 > iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    iError = avcodec_open2(pInputEncContext, pInputCodec, NULL);
    if (0 != iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    //打开输入文件结束

    for (UINT index = 0; index < pInputFormatCtx->nb_streams; ++index)
    {
        printf("===============================\n");
        printf("info Streams[%d]: %d\n", index, pInputFormatCtx->streams[index]->codecpar->codec_type);
        av_dump_format(pInputFormatCtx, index, szInputFileName, 0);
    }

    /********打开输出文件初始化 begin********/
    iError = avformat_alloc_output_context2(&pOutputFormatCtx, NULL, NULL, szOutputFileName);
    if (0 > iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    out_streams = new AVStream * [pInputFormatCtx->nb_streams];
    memset(out_streams, 0, pInputFormatCtx->nb_streams * sizeof(AVStream*));
    for (UINT uStreamIndex = 0; uStreamIndex < pInputFormatCtx->nb_streams; ++uStreamIndex)
    {
        out_streams[uStreamIndex] = avformat_new_stream(pOutputFormatCtx, NULL);
        avcodec_parameters_copy(out_streams[uStreamIndex]->codecpar, pInputFormatCtx->streams[uStreamIndex]->codecpar);
        out_streams[uStreamIndex]->codecpar->codec_tag = 0;
    }


    pOutCodec = avcodec_find_encoder(pOutputFormatCtx->streams[iVideoStream]->codecpar->codec_id);
    if (NULL == pOutCodec)
    {
        goto FUN_CLEANUP_INPUT;
    }

    pOutputEncContext = avcodec_alloc_context3(pOutCodec);
    iError = avcodec_parameters_to_context(pOutputEncContext, pOutputFormatCtx->streams[iVideoStream]->codecpar);
    if (0 > iError)
    {
        goto FUN_CLEANUP_INPUT;
    }

    pOutputEncContext->time_base.den = pInputFormatCtx->streams[iVideoStream]->avg_frame_rate.den;
    pOutputEncContext->time_base.num = pInputFormatCtx->streams[iVideoStream]->avg_frame_rate.num;
    pOutputEncContext->sample_aspect_ratio = pInputEncContext->sample_aspect_ratio;
    pOutputEncContext->width = pInputEncContext->width;
    pOutputEncContext->height = pInputEncContext->height;
    /*pOutputEncContext->gop_size = 10;
    pOutputEncContext->max_b_frames = 1;*/

    iError = avcodec_open2(pOutputEncContext, pOutCodec, NULL);
    if (0 != iError)
    {
        goto FUN_CLEANUP_INPUT;
    }


    if (!(pOutputFormatCtx->oformat->flags & AVFMT_NOFILE))
    {
        iError = avio_open(&pOutputFormatCtx->pb, szOutputFileName, AVIO_FLAG_WRITE);
    }

    printf("Output=======================================================\n");

    for (UINT index = 0; index < pOutputFormatCtx->nb_streams; ++index)
    {
        printf("===============================\n");
        printf("info Streams[%d]: %d\n", index, pOutputFormatCtx->streams[index]->codecpar->codec_type);
        av_dump_format(pOutputFormatCtx, index, szOutputFileName, 1);
    }

    avformat_write_header(pOutputFormatCtx, NULL);

    /********打开输出文件初始化 end********/


    //初始化滤镜开始
    iError = InitFilter();
    if (0 != iError)
    {
        goto FUN_CLEANUP_INPUT;
    }
    //初始化滤镜结束


    frameinput = av_frame_alloc();
    if (NULL == frameinput)
    {
        goto FUN_CLEANUP_INPUT;
    }

    framefilt = av_frame_alloc();
    if (NULL == framefilt)
    {
        goto FUN_CLEANUP_INPUT;
    }

    while (true)
    {
        iError = av_read_frame(pInputFormatCtx, &packetinput);
        if (0 > iError)
        {
            break;
        }

        av_packet_rescale_ts(&packetinput, pInputFormatCtx->streams[packetinput.stream_index]->time_base, out_streams[packetinput.stream_index]->time_base);

        if (packetinput.stream_index == iVideoStream)
        {
            iError = avcodec_send_packet(pInputEncContext, &packetinput);
            if (0 != iError)
            {
                break;
            }

            while (iError >= 0)
            {
                iError = avcodec_receive_frame(pInputEncContext, frameinput);
                if (iError == AVERROR(EAGAIN) || iError == AVERROR_EOF)
                {
                    break;
                }
                else if (iError < 0)
                {
                    goto FUN_CLEANUP_INPUT;
                }

                frameinput->pts = frameinput->best_effort_timestamp;

                iError = av_buffersrc_add_frame_flags(filtBufferSrcCtx, frameinput, AV_BUFFERSRC_FLAG_KEEP_REF);
                if (0 > iError)
                {
                    break;
                }

                while (true)
                {
                    iError = av_buffersink_get_frame(filtBufferSinkCtx, framefilt);
                    if (iError == AVERROR(EAGAIN) || iError == AVERROR_EOF)
                    {
                        break;
                    }

                    if (0 > iError)
                    {
                        goto FUN_CLEANUP_INPUT;
                    }

                    iError = avcodec_send_frame(pOutputEncContext, framefilt);
                    if (0 > iError)
                    {
                        goto FUN_CLEANUP_INPUT;
                    }

                    while (iError >= 0)
                    {
                        iError = avcodec_receive_packet(pOutputEncContext, &packetoutput);
                        if (iError == AVERROR(EAGAIN) || iError == AVERROR_EOF)
                        {
                            break;
                        }
                        else if (iError < 0)
                        {
                            goto FUN_CLEANUP_INPUT;
                        }


                        av_write_frame(pOutputFormatCtx, &packetoutput);

                        av_packet_unref(&packetoutput);
                    }

                    av_frame_unref(framefilt);
                }

            }

        }
        else
        {

            //其他流
            av_write_frame(pOutputFormatCtx, &packetinput);
        }
    }


    av_write_trailer(pOutputFormatCtx);



FUN_CLEANUP_INPUT:
    if (NULL != pInputFormatCtx)
    {
        avformat_close_input(&pInputFormatCtx);
        pInputFormatCtx = NULL;
    }

    if (NULL != pInputEncContext)
    {
        avcodec_free_context(&pInputEncContext);
        pInputEncContext = NULL;
    }

    if (NULL != frameinput)
    {
        av_frame_free(&frameinput);
        frameinput = NULL;
    }

    if (NULL != framefilt)
    {
        av_frame_free(&framefilt);
        framefilt = NULL;
    }

    if (NULL != pOutputFormatCtx)
    {
        avformat_free_context(pOutputFormatCtx);
        pOutputFormatCtx = NULL;
    }

    if (NULL != out_streams)
    {
        delete[] out_streams;
        out_streams = NULL;

    }

    if (NULL != pOutputFormatCtx)
    {
        avformat_free_context(pOutputFormatCtx);
        pOutputFormatCtx = NULL;
    }

    if (NULL != pOutputEncContext)
    {
        avcodec_free_context(&pOutputEncContext);
        pOutputEncContext = NULL;
    }

    /*avcodec_close();
    avformat_free_context();*/

    system("pause");
    return 0;
}


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答 默认 最新

相关推荐