extern const PixFmtInfo pix_fmt_info[] 的链接问题

本文深入解析了FFmpeg中利用C99特性进行结构体成员初始化的方式,并针对在VS2008环境下可能遇到的兼容性问题提供了详细的解决方案,包括调整数组成员顺序和修改特定语法以适应该编译器的限制。

在ffmpeg中,大量使用了c99中的结构体成员初始化方式,如libavcodec\imgconvert.c中的一个定义:

/* this table gives more information about formats */

static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {

    /* YUV formats */

    [PIX_FMT_YUV420P] = {

        .name = "yuv420p",

        .nb_channels = 3,

        .color_type = FF_COLOR_YUV,

        .pixel_type = FF_PIXEL_PLANAR,

        .depth = 8,

        .x_chroma_shift = 1, .y_chroma_shift = 1,

    },

    [PIX_FMT_YUV422P] = {

        .name = "yuv422p",

        .nb_channels = 3,

        .color_type = FF_COLOR_YUV,

        .pixel_type = FF_PIXEL_PLANAR,

        .depth = 8,

        .x_chroma_shift = 1, .y_chroma_shift = 0,

    },

………..

};

这一段代码在vs2008下编译将产生很多语法错误,首先在这个结构体数组中,它使用了[PIX_FMT_*]这样的方式指定序号,这样数组的成员可以不必要按照顺序排列,但是在vs2008下,必须调整数组成员的顺序,使之按递增的顺序排列。此外,vs2008也不支持.name = “”这样的定义,因此可以做出如下修改:

/* this table gives more information about formats */

static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {

    /* YUV formats */

    /*[PIX_FMT_YUV420P] =*/ { // PIX_FMT_YUV420P = 0

        /*.name = */"yuv420p",

        /*.nb_channels = */3,

        /*.color_type = */FF_COLOR_YUV,

        /*.pixel_type = */FF_PIXEL_PLANAR,

         /*.is_alpha = */0,

        /*.x_chroma_shift = */1,

         /*.y_chroma_shift = */1,

        /*.depth = */8,

    },

    /*[PIX_FMT_YUYV422] =*/ {    // PIX_FMT_YUYV422 = 1

        /*.name = */"yuyv422",

        /*.nb_channels = */1,

        /*.color_type = */FF_COLOR_YUV,

        /*.pixel_type = */FF_PIXEL_PACKED,

         /*.is_alpha = */0,

        /*.x_chroma_shift = */1,

         /*.y_chroma_shift = */0,

        /*.depth = */8,

    },

    /*[PIX_FMT_RGB24] =*/ {      // PIX_FMT_RGB24 = 2

        /*.name = */"rgb24",

        /*.nb_channels = */3,

        /*.color_type = */FF_COLOR_RGB,

        /*.pixel_type = */FF_PIXEL_PACKED,

         /*.is_alpha = */0,

        /*.x_chroma_shift = */0,

         /*.y_chroma_shift = */0,

        /*.depth = */8,

    },

………….

};

转载请标明出处: http://blog.youkuaiyun.com/lights_joy/archive/2008/12/11/3500595.aspx
include <QImage> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> } void initRTSPStream(const char* outputUrl, int width, int height) { // 注册FFmpeg组件 avformat_network_init(); AVOutputFormat *fmt = av_guess_format("rtsp", NULL, NULL); AVFormatContext *oc = NULL; avformat_alloc_output_context2(&oc, fmt, "rtsp", outputUrl); // 添加视频流 AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264); AVStream *stream = avformat_new_stream(oc, codec); // 配置编码参数 AVCodecContext *c = stream->codec; c->codec_id = AV_CODEC_ID_H264; c->bit_rate = 400000; c->width = width; c->height = height; c->time_base = (AVRational){1, 25}; // 25 FPS c->pix_fmt = AV_PIX_FMT_YUV420P; // 打开输出流 avio_open(&oc->pb, outputUrl, AVIO_FLAG_WRITE); avformat_write_header(oc, NULL); } void pushImageAsFrame(AVFormatContext *oc, const QImage &image) { static SwsContext *swsCtx = NULL; AVStream *stream = oc->streams[0]; AVCodecContext *c = stream->codec; // 初始化图像转换器 if (!swsCtx) { swsCtx = sws_getContext(image.width(), image.height(), AV_PIX_FMT_RGB32, c->width, c->height, c->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL); } // 创建视频帧 AVFrame *frame = av_frame_alloc(); frame->format = c->pix_fmt; frame->width = c->width; frame->height = c->height; av_frame_get_buffer(frame, 32); // 转换QImage到YUV格式 uint8_t *srcData[1] = { (uint8_t*)image.bits() }; int srcLinesize[1] = { image.bytesPerLine() }; sws_scale(swsCtx, srcData, srcLinesize, 0, image.height(), frame->data, frame->linesize); // 设置时间戳 frame->pts = av_rescale_q(stream->nb_frames, c->time_base, stream->time_base); // 编码并发送帧 AVPacket pkt = {0}; av_init_packet(&pkt); int got_output; avcodec_encode_video2(c, &pkt, frame, &got_output); if (got_output) { av_interleaved_write_frame(oc, &pkt); av_packet_unref(&pkt); } av_frame_free(&frame); } void startImageStreaming() { const char *rtspUrl = "rtsp://yourserver:8554/mystream"; int width = 640; int height = 480; // 初始化流 AVFormatContext *oc = initRTSPStream(rtspUrl, width, height); // 循环推送图片 for (int i = 0; i < imageCount; ++i) { QImage img(QString("image%1.png").arg(i)); pushImageAsFrame(oc, img); QThread::msleep(40); // 25FPS延迟 } // 清理资源 av_write_trailer(oc); avio_close(oc->pb); avformat_free_context(oc); }你看看你写的代码, AVFormatContext *oc = initRTSPStream(rtspUrl, width, height);怎么用
08-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值