C#音视频网络流解码:H264视频和ACC音频
下面两种方式是直接翻译过来的,还有问题,比如指针的使用和值的传入。考虑C#和C++的差异,还是要抱着怀疑的态度去看待,不一定是对的。
H264视频解码网络流:
using FFmpeg.AutoGen;
using RTForwardServer;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
/// <summary>
/// http://blog.csdn.net/jammg/article/details/52750241
/// </summary>
namespace AVParser.Parser
{
public unsafe class H264Parser
{ public PictureBox ShowPictureBox {set;get;} /// <summary>
/// 解码H264网络流
/// </summary>
/// <param name="socket">Socket对象</param>
public unsafe void Parser(Socket socket) {
AVCodecContext* pCodecCtx = null;
AVCodecParserContext* pCodecParserCtx = null;
AVCodec* pCodec = null;
AVFrame* pFrame = null; //yuv
AVPacket packet; //h264
AVPicture picture; //储存rgb格式图片
SwsContext* pSwsCtx = null;
AVCodecID codec_id = AVCodecID.AV_CODEC_ID_H264; int ret; //FFmpeg可执行二进制命令工具查找
//FFmpegBinariesHelper.RegisterFFmpegBinaries(); //ffmpeg.av_register_all();
//ffmpeg.avcodec_register_all(); /* 初始化AVCodec */
pCodec = ffmpeg.avcodec_find_decoder(codec_id); /* 初始化AVCodecContext,只是分配,还没打开 */
pCodecCtx = ffmpeg.avcodec_alloc_context3(pCodec); /* 初始化AVCodecParserContext */
pCodecParserCtx = ffmpeg.av_parser_init((int)AVCodecID.AV_CODEC_ID_H264);
if (null==pCodecParserCtx)
{
return;//终止执行
} /* we do not send complete frames,什么意思? */
if (pCodec->capabilities > 0 && ffmpeg.CODEC_CAP_TRUNCATED > 0)
pCodecCtx->flags |= ffmpeg.CODEC_FLAG_TRUNCATED; /* 打开解码器 */
ret = ffmpeg.avcodec_open2(pCodecCtx, pCodec, null);
if (ret < 0)
{
return;//终止执行
} pFrame = ffmpeg.av_frame_alloc();
ffmpeg.av_init_packet(&packet);
packet.size = 0;
packet.data = null; const int in_buffer_size = 4096;
//uint in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
byte[] in_buffer=new byte[in_buffer_size];
byte *cur_ptr;
int cur_size;
int got;
bool is_first_time = true; while (true)
{
// Socket通信实例接收信息
//cur_size = 0;//recv(m_socket, (char*)in_buffer, in_buffer_size, 0);
cur_size = socket.Receive(in_buffer, in_buffer_size, SocketFlags.None);
Console.WriteLine("H264Parser Socket Receive: data byte string={0}", BitConverter.ToString(in_buffer));
if (cur_size == 0)
break; //cur_ptr = in_buffer;//指针转换问题
cur_ptr = (byte*)ffmpeg.av_malloc(in_buffer_size);
while (cur_size > 0)
{
/* 返回解析了的字节数 */
int len = ffmpeg.av_parser_parse2(pCodecParserCtx, pCodecCtx,
&packet.data, &packet.size, (byte*)cur_ptr, cur_size,
ffmpeg.AV_NOPTS_VALUE, ffmpeg.AV_NOPTS_VALUE, ffmpeg.AV_NOPTS_VALUE);
cur_ptr += len;
cur_size -= len;
if (packet.size == 0)
continue; //switch (pCodecParserCtx->pict_type)
//{
// case AV_PICTURE_TYPE_I: printf("Type: I\t"); break;
// case AV_PICTURE_TYPE_P: printf("Type: P\t"); break;
// case AV_PICTURE_TYPE_B: printf("Type: B\t"); break;
// default: printf("Type: Other\t"); break;
//}
//printf("Output Number:%4d\t", pCodecParserCtx->output_picture_number);
//printf("Offset:%8ld\n", pCodecParserCtx->cur_offset);
ret = ffmpeg.avcodec_decode_video2(pCodecCtx, pFrame, &got, &packet);
if (ret < 0)
{
return;//终止执行
} if (got>0)
{
if (is_first_time) //分配格式转换存储空间
{
// C AV_PIX_FMT_RGB32 统一改为 AVPixelFormat.AV_PIX_FMT_RGB24
pSwsCtx = ffmpeg.sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AVPixelFormat.AV_PIX_FMT_RGB24, ffmpeg.SWS_BICUBIC, null, null, null); ffmpeg.avpicture_alloc(&picture, AVPixelFormat.AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); is_first_time = false;
}
/* YUV转RGB */
ffmpeg.sws_scale(pSwsCtx, pFrame->data, pFrame->linesize,
0, pCodecCtx->height,
picture.data, picture.linesize); //QImage img(picture.data[0], pCodecCtx->width, pCodecCtx->height, QImage::Format_RGB32); //emit this-> signal_receive_one_image(img); //填充视频帧
//ffmpeg.avpicture_fill((AVPicture*)pFrame, cur_ptr, AVPixelFormat.AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); #region 构造图片
var dstData = new byte_ptrArray4();// 声明形参
var dstLinesize = new int_array4();// 声明形参
// 目标媒体格式需要的字节长度
var convertedFrameBufferSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
// 分配目标媒体格式内存使用
var convertedFrameBufferPtr = Marshal.AllocHGlobal(convertedFrameBufferSize);
// 设置图像填充参数
ffmpeg.av_image_fill_arrays(ref dstData, ref dstLinesize, (byte*)convertedFrameBufferPtr, AVPixelFormat.AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1); // 封装Bitmap图片
var bitmap = new Bitmap(pCodecCtx->width, pCodecCtx->height, dstLinesize[0], PixelFormat.Format24bppRgb, convertedFrameBufferPtr);
ShowPictureBox.Image = bitmap;
ShowPictureBox.Dispose();
#endregion
}
}
}
ShowPictureBox.Image = null;
ShowPictureBox.Dispose(); ffmpeg.av_free_packet(&packet);
ffmpeg.av_frame_free(&pFrame);
ffmpeg.avpicture_free(&picture);
ffmpeg.sws_freeContext(pSwsCtx);
ffmpeg.avcodec_free_context(&pCodecCtx);
ffmpeg.av_parser_close(pCodecParserCtx);
} }
}
ACC音频解码网络流:
using FFmpeg.AutoGen;
using RTForwardServer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
/// <summary>
/// http://blog.csdn.net/jammg/article/details/52750241
/// </summary>
namespace AVParser.Parser
{
public unsafe class ACCParser
{ /// <summary>
/// 解码AAC音频
/// </summary>
/// <param name="socket">Socket对象</param>
public unsafe void Parser(Socket socket) {
AVCodecContext* pCodecCtx = null;
AVCodecParserContext* pCodecParserCtx = null;
AVCodec* pCodec = null;
AVFrame* pFrame = null;
AVPacket packet;
AVCodecID codec_id = AVCodecID.AV_CODEC_ID_AAC; int ret; //FFmpeg可执行二进制命令工具查找
//FFmpegBinariesHelper.RegisterFFmpegBinaries(); //ffmpeg.av_register_all();
//ffmpeg.avcodec_register_all(); /* 初始化AVCodec */
pCodec = ffmpeg.avcodec_find_decoder(codec_id); /* 初始化AVCodecContext,只是分配,还没打开 */
pCodecCtx = ffmpeg.avcodec_alloc_context3(pCodec); /* 初始化AVCodecParserContext */
pCodecParserCtx = ffmpeg.av_parser_init((int)AVCodecID.AV_CODEC_ID_AAC);
if (null==pCodecParserCtx)
{
Application.Exit();//退出程序
} /* we do not send complete frames,什么意思? */
if (pCodec->capabilities>0 && ffmpeg.CODEC_CAP_TRUNCATED > 0)
pCodecCtx->flags |= ffmpeg.CODEC_FLAG_TRUNCATED; /* 打开解码器 */
ret = ffmpeg.avcodec_open2(pCodecCtx, pCodec, null);
if (ret < 0)
{
return ;//终止执行
} pFrame = ffmpeg.av_frame_alloc();
ffmpeg.av_init_packet(&packet);
packet.size = 0;
packet.data = null; /* 存储一帧可以PCM,L(一个采样点)RLRLR..... ,用于播放 */
int out_buf_size=0;
byte* out_buf = null; //FILE *fp = fopen("audio.pcm", "wb"); const int in_buffer_size = 4096;
/**
* AVPacket.buf.data 指向AVPacket.data ,AVPacket.buf.size = AVPacket.size + FF_INPUT_BUFFER_PADDING_SIZE
*/ //uint8_t in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
//uint [] in_buffer =new uint[in_buffer_size];
byte [] in_buffer = new byte[in_buffer_size];
byte *cur_ptr;
int cur_size;
int got;
bool is_first_time = true; while (true)
{
// Socket通信实例接收信息
//cur_size = 0;//recv(m_socket, (char*)in_buffer, in_buffer_size, 0);
cur_size = socket.Receive(in_buffer, in_buffer.Length, SocketFlags.None);
Console.WriteLine("ACCParser Socket Receive: data byte string={0}", BitConverter.ToString(in_buffer));
if (cur_size == 0)
break;
//cur_ptr = in_buffer;//指针转换问题
cur_ptr = (byte*)ffmpeg.av_malloc(in_buffer_size);
while (cur_size > 0)
{
/* 返回解析了的字节数 */
int len = ffmpeg.av_parser_parse2(pCodecParserCtx, pCodecCtx,
&packet.data, &packet.size, cur_ptr, cur_size,
ffmpeg.AV_NOPTS_VALUE, ffmpeg.AV_NOPTS_VALUE, ffmpeg.AV_NOPTS_VALUE);
cur_ptr += len;
cur_size -= len;
if (packet.size == 0)
continue; ret = ffmpeg.avcodec_decode_audio4(pCodecCtx, pFrame, &got, &packet);
if (ret < 0)
{
return;//终止执行
} if (got>0)
{
if (is_first_time) //分配格式转换存储空间
{ out_buf_size = ffmpeg.av_samples_get_buffer_size(
null,
pCodecCtx->channels,
pFrame->nb_samples, //读取一帧数据时每个声道读取的采样个数
pCodecCtx->sample_fmt,
1); out_buf = (byte*)ffmpeg.av_malloc((ulong)out_buf_size);
if (out_buf == null)
{
return;//终止执行
} is_first_time = false;
} UInt32* l = (UInt32*)pFrame->extended_data[0];
UInt32* r = (UInt32*)pFrame->extended_data[1]; //这里是针对AV_SAMPLE_FMT_FLTP格式的写入方式,其他音频格式的需要其他方式
for (int i = 0, j = 0; i < out_buf_size; i += 8, j++)
{
out_buf[i] = (byte)(r[j] & 0xff);
out_buf[i + 1] = (byte)(r[j] >> 8 & 0xff);
out_buf[i + 2] = (byte)(r[j] >> 16 & 0xff);
out_buf[i + 3] = (byte)(r[j] >> 24 & 0xff); out_buf[i + 4] = (byte)(l[j] & 0xff);
out_buf[i + 5] = (byte)(l[j] >> 8 & 0xff);
out_buf[i + 6] = (byte)(l[j] >> 16 & 0xff);
out_buf[i + 7] = (byte)(l[j] >> 24 & 0xff);
} //std::string str(out_buf, out_buf_size);
//emit this->signal_receive_one_audio_frame(str); //fwrite(out_buf, out_buf_size, 1, fp); //填充音频帧==此处似乎不再需要填充音频帧数据
//ffmpeg.avcodec_fill_audio_frame(pFrame, pFrame->channels,AVSampleFormat.AV_SAMPLE_FMT_FLTP,out_buf, out_buf_size,0); // byte*转为byte[]
byte[] bytes = new byte[out_buf_size];
for (int i = 0; i < out_buf_size; i++)
{
bytes[i] = out_buf[i];
} // 播放音频数据
MemoryStream ms = new MemoryStream(bytes);
SoundPlayer sp = new SoundPlayer(ms);
sp.Play();
}
}
} ffmpeg.av_free_packet(&packet);
ffmpeg.av_frame_free(&pFrame);
ffmpeg.avcodec_free_context(&pCodecCtx);
ffmpeg.av_parser_close(pCodecParserCtx);
} }
}
C#音视频网络流解码:H264视频和ACC音频的更多相关文章
- iPhone调用ffmpeg2.0.2解码h264视频的示例代码
iPhone调用ffmpeg2.0.2解码h264视频的示例代码 h264demo.zip 关于怎么在MAC下编译iOS下的ffmpeg请看 编译最新ffmpeg2.0.1(ffmpeg2.0.2)到 ...
- 使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧
前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境.以下就来问个样例: 1.利用x264库将YUV格式视频文件编码为h264格式视频文件 2.利用ffmpeh库将h264格 ...
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...
- Android 音视频编解码——YUV视频格式详解
一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...
- 音视频编解码——YUV视频格式详解
一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...
- 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...
- 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...
- 音视频编解码技术(一):MPEG-4/H.264 AVC 编解码标准
一.H264 概述 H.264,通常也被称之为H.264/AVC(或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC) 1. H.264视频编解码的意义 H.264的出现就是为了创 ...
- 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解
http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...
随机推荐
- 【朱-刘算法】【最小树形图】hdu6141 I am your Father!
题意:给你一张带权有向图,让你求最大树形图.并在此前提下令n号结点父亲的编号最小. 比赛的时候套了个二分,TLE了. 实际上可以给每个边的权值乘1000,对于n号结点的父边,加上(999-父结点编号) ...
- 重拾vue2
Vue组件 一.组件介绍 每一个组件都是一个vue实例 每个组件均具有自身的模板template,根组件的模板就是挂载点 每个组件模板只能拥有一个根标签 子组件的数据具有作用域,以达到组件的复用 二. ...
- Java学习笔记(15)
iterator方法 迭代器的作用:就是用于抓取集合中的元素 注:迭代器返回的一个接口类型的实现类,是一种多态的用法,而不是接口在调用方法 public class Demo2 { public st ...
- session cookie的区别最全总结
作为一名WEB开发程序员,对session的理解是最基础的,但是现状是WEB程序员遍地都是,随便一划拉一大把,不过估计能把session能透彻理解的人应该不是很多,起码我之前对此是知之甚少,偶然看到的 ...
- ps制作导航条 分割线技巧
1 用矩形工具画一个像素的矩形(注意不是路径) 2给矩形添加蒙版,用渐变工具对其进行渐变,达到两头渐隐藏的效果. 制作按钮技巧 用矩形工具画出矩形 然后给矩形添加 内发光 渐变叠加 光泽 描边等操作 ...
- HMAC结合“挑战/响应”保障数据传输安全
1.流程图: HMAC的一个典型应用是结合“挑战/响应”(Challenge/Response)来保障客户端和服务器传输数据的安全性 . 2.安全性分析: 使用的密钥是双方事先约定的,第三方不可能知道 ...
- 微软浏览器兼容工具modern.IE
http://www.browserstack.com/screenshots
- js中定义变量的三种方式const,val,let 的区别
js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始 ...
- 关停后Bitfinex放贷初探
据说Bitfinex放贷平均日息可达0.1%,现在就此做一番调研: 真的很先进,利率也像牌价一样挂卖: 1.美元利率为0.06%/天 2.美元利率最高,数币较低 参考资料:不买比特币也能赚钱,Bitf ...
- [Java]利用javax.swing.Timer类在窗口上实现动画效果
javax.swing.Timer类在创建时需要指定时间间隔和定时器到时间需要执行的动作,即ActionListener. Timer timer = new Timer(100, taskPerfo ...