ffmpeg推送图片到流媒体服务器

直接上源码

#include "stdafx.h"

#include <stdio.h>  

#include "opencv2/opencv.hpp"

#define __STDC_CONSTANT_MACROS  

using namespace cv;

 

extern "C"

{

#include "libavformat/avformat.h"  

#include "libavutil/mathematics.h"  

#include "libavformat/avformat.h"

#include "libswscale/swscale.h"

#include "libavutil/time.h"  

};

 

#include<string.h>  

#include<malloc.h>  

 

#pragma pack(1)  

 

int main()

{

 

typedef struct tagBITMAPFILEHEADER

{

unsigned short  bfType; //2 位图文件的类型,必须为“BM”  

unsigned long bfSize; //4 位图文件的大小,以字节为单位  

unsigned short bfReserved1; //2 位图文件保留字,必须为0  

unsigned short bfReserved2; //2 位图文件保留字,必须为0  

unsigned long bfOffBits; //4 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位  

} BITMAPFILEHEADER;//该结构占据14个字节。  

 

typedef struct tagBITMAPINFOHEADER {

unsigned long biSize; //4 本结构所占用字节数  

long biWidth; //4 位图的宽度,以像素为单位  

long biHeight; //4 位图的高度,以像素为单位  

unsigned short biPlanes; //2 目标设备的平面数不清,必须为1  

unsigned short biBitCount;//2 每个像素所需的位数,必须是1(双色), 4(16色),8(256色)或24(真彩色)之一  

unsigned long biCompression; //4 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一  

unsigned long biSizeImage; //4 位图的大小,以字节为单位  

long biXPelsPerMeter; //4 位图水平分辨率,每米像素数  

long biYPelsPerMeter; //4 位图垂直分辨率,每米像素数  

unsigned long biClrUsed;//4 位图实际使用的颜色表中的颜色数  

unsigned long biClrImportant;//4 位图显示过程中重要的颜色数  

} BITMAPINFOHEADER;//该结构占据40个字节。  

 

int nWidth = 0;

int nHeight = 0;

 

int nDataLen = 0;

 

int nLen;

 

char csFileName[20];

//char csFileName[20];

 

int fileI;

unsigned char *pBmpBuf;

for (fileI = 1; fileI <= 1; fileI++)

{

sprintf(csFileName, "bmp/%d.bmp", fileI);

printf("%s\n", csFileName);

 

FILE *fp;

if ((fp = fopen(csFileName, "rb")) == NULL)  //以二进制的方式打开文件  

{

return FALSE;

}

WORD fileType;

fread(&fileType, 1, sizeof(WORD), fp);

if (fileType != 0x4d42)

{

printf("file is not .bmp file!");

system("pause");

return 0;

}

 

if (fseek(fp, sizeof(BITMAPFILEHEADER), 0))  //跳过BITMAPFILEHEADE  

{

return FALSE;

}

BITMAPINFOHEADER infoHead;

fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);   //从fp中读取BITMAPINFOHEADER信息到infoHead中,同时fp的指针移动  

nWidth = infoHead.biWidth;

nHeight = infoHead.biHeight;

int linebyte = (nWidth * 24 / 8 + 3) / 4 * 4; //计算每行的字节数,24:该图片是24位的bmp图,3:确保不丢失像素  

 

  //cout<<bmpwidth<<" "<<bmpheight<<endl;  

nDataLen = linebyte*nHeight;

pBmpBuf = new unsigned char[linebyte*nHeight];

fread(pBmpBuf, sizeof(char), linebyte*nHeight, fp);

fclose(fp);

}

printf("file ok\n");

av_register_all();

avcodec_register_all();

AVFrame *m_pRGBFrame = new AVFrame[1];  //RGB帧数据      

AVFrame *m_pYUVFrame = new AVFrame[1];;  //YUV帧数据    

AVCodecContext *c = NULL;

AVCodecContext *in_c = NULL;

AVCodec *pCodecH264; //编码器    

uint8_t * yuv_buff;//    

 

   //查找h264编码器    

pCodecH264 = avcodec_find_encoder(AV_CODEC_ID_H264);

 

 

c = avcodec_alloc_context3(pCodecH264);

c->bit_rate = 3000000;// put sample parameters     

c->width = nWidth;//     

c->height = nHeight;//     

 

// frames per second     

AVRational rate;

rate.num = 1;

rate.den = 5;

c->time_base = rate;//(AVRational){1,25};    

c->gop_size = 10; // emit one intra frame every ten frames     

c->max_b_frames = 1;

c->thread_count = 1;

c->pix_fmt = AV_PIX_FMT_YUV420P;//PIX_FMT_RGB24;    

 

//av_opt_set(c->priv_data, /*"preset"*/"libvpx-1080p.ffpreset", /*"slow"*/NULL, 0);    

//打开编码器    

if (avcodec_open2(c, pCodecH264, NULL)<0)

printf("不能打开编码库");

 

int size = c->width * c->height;

 

yuv_buff = (uint8_t *)malloc((size * 3) / 2); // size for YUV 420     

 

  //将rgb图像数据填充rgb帧    

uint8_t * rgb_buff = new uint8_t[nDataLen];

 

//图象编码    

int outbuf_size = 100000;

uint8_t * outbuf = (uint8_t*)malloc(outbuf_size);

int u_size = 0;

/*FILE *h264_f = NULL;

const char * filename = "0_Data.h264";

h264_f = fopen(filename, "wb");

if (!h264_f)

{

printf("could not open %s\n", filename);

exit(1);

}*/

 

//初始化SwsContext    

SwsContext * scxt = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24, c->width, c->height, AV_PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);

 

AVPacket avpkt;

 

//-----lbg----------

AVOutputFormat *ofmt = NULL;

//输入对应一个AVFormatContext,输出对应一个AVFormatContext  

//(Input AVFormatContext and Output AVFormatContext)  

AVFormatContext  *ofmt_ctx = NULL;

//AVPacket pkt;

const char *in_filename, *out_filename;

int ret, i;

int videoindex = -1;

int frame_index = 0;

int64_t start_time = 0;

 

//in_filename = "F:/FeigeDownload/007.avi";//输入URL(Input file URL)  

//in_filename  = "shanghai03_p.h264";  

 

out_filename = "rtsp://192.168.0.104/test1";//输出 URL(Output URL)[RTMP]  

//out_filename = "rtp://233.233.233.233:6666";//输出 URL(Output URL)[UDP]  

 

av_register_all();

//Network  

avformat_network_init();

 

//输出(Output)  

 

avformat_alloc_output_context2(&ofmt_ctx, NULL, "rtsp", out_filename); //RTMP  

   //avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDP  

 

if (!ofmt_ctx) {

printf("Could not create output context\n");

ret = AVERROR_UNKNOWN;

goto end;

}

ofmt = ofmt_ctx->oformat;

//for (i = 0; i < ifmt_ctx->nb_streams; i++) {

//根据输入流创建输出流(Create output AVStream according to input AVStream)  

//AVStream *in_stream = ifmt_ctx->streams[i];

//AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);

AVStream *out_stream = avformat_new_stream(ofmt_ctx, pCodecH264);

if (!out_stream) {

printf("Failed allocating output stream\n");

ret = AVERROR_UNKNOWN;

goto end;

}

//复制AVCodecContext的设置(Copy the settings of AVCodecContext)  

/*ret = avcodec_copy_context(out_stream->codec, in_stream->codec);

if (ret < 0) {

printf("Failed to copy context from input to output stream codec context\n");

goto end;

}*/

 

 

ret = avcodec_copy_context(out_stream->codec, c);

if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)

out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

//}

//Dump Format------------------  

av_dump_format(ofmt_ctx, 0, out_filename, 1);

//打开输出URL(Open output URL)  

if (!(ofmt->flags & AVFMT_NOFILE)) {

ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);

if (ret < 0) {

printf("Could not open output URL '%s'", out_filename);

goto end;

}

}

//写文件头(Write file header)  

 

ret = avformat_write_header(ofmt_ctx, NULL);

if (ret < 0) {

printf("Error occurred when opening output URL\n");

goto end;

}

//----------------

int duation = 0;

//AVFrame *pTFrame=new AVFrame    

for (int i = 0; i<250000; ++i)

{

 

//AVFrame *m_pYUVFrame = new AVFrame[1];    

 

int index = i % 200 + 1;

 

sprintf(csFileName, "bmp/%d.bmp", index);

printf("%s\n", csFileName);

 

FILE *fp;

if ((fp = fopen(csFileName, "rb")) == NULL)  //以二进制的方式打开文件  

{

return FALSE;

}

WORD fileType;

fread(&fileType, 1, sizeof(WORD), fp);

if (fileType != 0x4d42)

{

printf("file is not .bmp file!");

system("pause");

return 0;

}

 

if (fseek(fp, sizeof(BITMAPFILEHEADER), 0))  //跳过BITMAPFILEHEADE  

{

return FALSE;

}

BITMAPINFOHEADER infoHead;

fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);   //从fp中读取BITMAPINFOHEADER信息到infoHead中,同时fp的指针移动  

nWidth = infoHead.biWidth;

nHeight = infoHead.biHeight;

int linebyte = (nWidth * 24 / 8 + 3) / 4 * 4; //计算每行的字节数,24:该图片是24位的bmp图,3:确保不丢失像素  

 

  //cout<<bmpwidth<<" "<<bmpheight<<endl;  

nDataLen = linebyte*nHeight;

pBmpBuf = new unsigned char[linebyte*nHeight];

fread(pBmpBuf, sizeof(char), linebyte*nHeight, fp);

fclose(fp);

memcpy(rgb_buff, pBmpBuf, nDataLen);

 

 

avpicture_fill((AVPicture*)m_pRGBFrame, (uint8_t*)rgb_buff, AV_PIX_FMT_RGB24, nWidth, nHeight);

 

//将YUV buffer 填充YUV Frame    

avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)yuv_buff, AV_PIX_FMT_YUV420P, nWidth, nHeight);

 

// 翻转RGB图像    

m_pRGBFrame->data[0] += m_pRGBFrame->linesize[0] * (nHeight - 1);

m_pRGBFrame->linesize[0] *= -1;

m_pRGBFrame->data[1] += m_pRGBFrame->linesize[1] * (nHeight / 2 - 1);

m_pRGBFrame->linesize[1] *= -1;

m_pRGBFrame->data[2] += m_pRGBFrame->linesize[2] * (nHeight / 2 - 1);

m_pRGBFrame->linesize[2] *= -1;

 

 

//将RGB转化为YUV    

sws_scale(scxt, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);

 

int got_packet_ptr = 0;

av_init_packet(&avpkt);

avpkt.data = outbuf;

avpkt.size = outbuf_size;

u_size = avcodec_encode_video2(c, &avpkt, m_pYUVFrame, &got_packet_ptr);

m_pYUVFrame->pts++;

if (u_size == 0)

{

 

//avpkt.pts = av_rescale_q_rnd(avpkt.pts, c->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));

//avpkt.dts = av_rescale_q_rnd(avpkt.dts, c->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));

//avpkt.duration = av_rescale_q(avpkt.duration, c->time_base, out_stream->time_base);

 

 

time_t tt = time(NULL);//这句返回的只是一个时间cuo

tm* t = localtime(&tt);

 

int64_t i = *((int64_t*)&t);

 

 

avpkt.pts = duation;

avpkt.dts = duation;

avpkt.duration = 0;

duation += 18000;

avpkt.pos = -1;

ret = av_interleaved_write_frame(ofmt_ctx, &avpkt);

 

if (ret < 0) {

printf("Error muxing packet %d\n", ret);

}

else {

printf("Error muxing packet ok\n", ret);

}

//fwrite(avpkt.data, 1, avpkt.size, f);

 

}

}

 

//fclose(h264_f);

free(outbuf);

avcodec_close(c);

av_free(c);

 

  

av_write_trailer(ofmt_ctx);

end:

//avformat_close_input(&ifmt_ctx);

 

if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))

avio_close(ofmt_ctx->pb);

avformat_free_context(ofmt_ctx);

if (ret < 0 && ret != AVERROR_EOF) {

printf("Error occurred.\n");

return -1;

}

return 0;

}


项目名:push_img
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: 以下是一个使用Python和FFmpeg实时推送图片流到RTMP服务器的示例代码: ```python import cv2 import subprocess import numpy as np input_file = "input.jpg" stream_key = "your_stream_key" command = ['ffmpeg', '-re', '-f', 'image2pipe', '-pix_fmt', 'bgr24', '-i', '-', '-c:v', 'libx264', '-preset', 'veryfast', '-maxrate', '3000k', '-bufsize', '6000k', '-pix_fmt', 'yuv420p', '-g', '50', '-f', 'flv', 'rtmp://<your-server-ip>/live/' + stream_key] process = subprocess.Popen(command, stdin=subprocess.PIPE) while True: # 读取图片文件 img = cv2.imread(input_file) # 将图片转换为二进制格式 img_bin = cv2.imencode('.jpg', img)[1].tobytes() # 将二进制数据写入FFmpeg进程的标准输入流 process.stdin.write(img_bin) # 等待50毫秒 cv2.waitKey(50) ``` 请将`input_file`替换为您要推流图片文件的路径,将`stream_key`替换为服务器上创建的流密钥,并将`<your-server-ip>`替换为服务器的IP地址。 在运行这个代码之前,您需要安装OpenCV和FFmpeg。如果您没有安装OpenCV,请使用以下命令安装: ``` pip install opencv-python ``` 如果您没有安装FFmpeg,请使用以下命令安装: ``` sudo apt-get update sudo apt-get install ffmpeg ``` 希望这可以帮助您实时推送图片流到RTMP服务器。 ### 回答2: Python使用FFmpeg推送实时图片可以实现将图片连续处理并通过网络实时推送的效果。具体步骤如下: 1. 导入所需的库: ```python import subprocess import cv2 from PIL import Image ``` 2. 设定推送图片源: ```python image_path = "path_to_image.jpg" ``` 3. 设置FFmpeg推送命令: ```python command = [ 'ffmpeg', '-y', '-f', 'image2pipe', '-i', '-', '-r', '30', # 设置帧率 '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-b:v', '1024k', # 设置推送的视频比特率 '-f', 'flv', # 推送到FLV格式 'rtmp://localhost/live/stream' # 设置推送的目标URL ] ``` 4. 循环处理并推送图片: ```python while True: image = cv2.imread(image_path) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # OpenCV读取BGR格式图片,需要转换为RGB格式 image = Image.fromarray(image) # 将图片转换为字节流 image_bytes = image.tobytes() # 使用subprocess通过管道将图片发送给FFmpeg process = subprocess.Popen(command, stdin=subprocess.PIPE) process.stdin.write(image_bytes) process.stdin.close() ``` 5. 结束推送: ```python process.terminate() ``` 通过以上步骤,就可以使用Python和FFmpeg实现实时推送图片。这样,每次循环读取图片并将图片传给FFmpegFFmpeg会将图片编码并通过指定的RTMP URL实时推送出去。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值