ffmpeg处理rtmp/文件/rtsp的推流和拉流
ffmpeg处理rtmp/文件/rtsp的推流和拉流
- //info.h
 - #ifndef __INFO_H__
 - #define __INFO_H__
 - #include <string.h>
 - #include <stdio.h>
 - #endif
 
- //ffmpeg.h
 - #ifndef __FFMPEG_H__
 - #define __FFMPEG_H__
 - #include "info.h"
 - extern "C"
 - {
 - #include "libavformat/avformat.h"
 - #include "libavformat/avio.h"
 - #include "libavcodec/avcodec.h"
 - #include "libswscale/swscale.h"
 - #include "libavutil/avutil.h"
 - #include "libavutil/mathematics.h"
 - #include "libswresample/swresample.h"
 - #include "libavutil/opt.h"
 - #include "libavutil/channel_layout.h"
 - #include "libavutil/samplefmt.h"
 - #include "libavdevice/avdevice.h" //摄像头所用
 - #include "libavfilter/avfilter.h"
 - #include "libavutil/error.h"
 - #include "libavutil/mathematics.h"
 - #include "libavutil/time.h"
 - #include "inttypes.h"
 - #include "stdint.h"
 - };
 - #pragma comment(lib,"avformat.lib")
 - #pragma comment(lib,"avcodec.lib")
 - #pragma comment(lib,"avdevice.lib")
 - #pragma comment(lib,"avfilter.lib")
 - #pragma comment(lib,"avutil.lib")
 - #pragma comment(lib,"postproc.lib")
 - #pragma comment(lib,"swresample.lib")
 - #pragma comment(lib,"swscale.lib")
 - //#define INPUTURL "test.flv"
 - #define INPUTURL "rtmp://test1.com:1935/myapp/teststream1"
 - //#define OUTPUTURL "testnew.flv";
 - #define OUTPUTURL "rtmp://test1.com:1935/myapp/teststream1new"
 - //video param
 - extern int m_dwWidth;
 - extern int m_dwHeight;
 - extern double m_dbFrameRate; //帧率
 - extern AVCodecID video_codecID;
 - extern AVPixelFormat video_pixelfromat;
 - extern char spspps[100];
 - extern int spspps_size;
 - //audio param
 - extern int m_dwChannelCount; //声道
 - extern int m_dwBitsPerSample; //样本
 - extern int m_dwFrequency; //采样率
 - extern AVCodecID audio_codecID;
 - extern int audio_frame_size;
 - #define AUDIO_ID 0 //packet 中的ID ,如果先加入音频 pocket 则音频是 0 视频是1,否则相反
 - #define VEDIO_ID 1
 - extern int nRet; //状态标志
 - extern AVFormatContext* icodec;
 - extern AVInputFormat* ifmt;
 - extern char szError[256]; //错误字符串
 - extern AVFormatContext* oc ; //输出流context
 - extern AVOutputFormat* ofmt;
 - extern AVStream* video_st;
 - extern AVStream* audio_st;
 - extern AVCodec *audio_codec;
 - extern AVCodec *video_codec;
 - extern int video_stream_idx;
 - extern int audio_stream_idx;
 - extern AVPacket pkt;
 - extern AVBitStreamFilterContext * vbsf_aac_adtstoasc; //aac->adts to asc过滤器
 - static int m_nVideoTimeStamp = 0;
 - static int m_nAudioTimeStamp = 0;
 - int InitInput(char * Filename,AVFormatContext ** iframe_c,AVInputFormat** iinputframe);
 - int InitOutput();
 - AVStream * Add_output_stream_2(AVFormatContext* output_format_context,AVMediaType codec_type_t, AVCodecID codecID,AVCodec **codec);
 - int OpenCodec(AVStream * istream, AVCodec * icodec); //打开编解码器
 - void read_frame(AVFormatContext *oc); //从文件读取一帧数据根据ID读取不同的帧
 - void write_frame_3(AVFormatContext *oc,int ID,AVPacket pkt_t); //这个是根据传过来的buf 和size 写入文件
 - int Es2Mux_2(); //通过时间戳控制写入音视频帧顺序
 - int UintInput();
 - int UintOutput();
 - #endif
 
- //ffmpeg.cpp
 - #include "ffmpeg.h"
 - int nRet = 0;
 - AVFormatContext* icodec = NULL;
 - AVInputFormat* ifmt = NULL;
 - char szError[256];
 - AVFormatContext* oc = NULL;
 - AVOutputFormat* ofmt = NULL;
 - AVStream * video_st = NULL;
 - AVStream * audio_st = NULL;
 - AVCodec *audio_codec;
 - AVCodec *video_codec;
 - double audio_pts = 0.0;
 - double video_pts = 0.0;
 - int video_stream_idx = -1;
 - int audio_stream_idx = -1;
 - AVPacket pkt;
 - AVBitStreamFilterContext * vbsf_aac_adtstoasc = NULL;
 - //video param
 - int m_dwWidth = 0;
 - int m_dwHeight = 0;
 - double m_dbFrameRate = 25.0; //帧率
 - AVCodecID video_codecID = AV_CODEC_ID_H264;
 - AVPixelFormat video_pixelfromat = AV_PIX_FMT_YUV420P;
 - char spspps[100];
 - int spspps_size = 0;
 - //audio param
 - int m_dwChannelCount = 2; //声道
 - int m_dwBitsPerSample = 16; //样本
 - int m_dwFrequency = 44100; //采样率
 - AVCodecID audio_codecID = AV_CODEC_ID_AAC;
 - int audio_frame_size = 1024;
 - int InitInput(char * Filename,AVFormatContext ** iframe_c,AVInputFormat** iinputframe)
 - {
 - int i = 0;
 - nRet = avformat_open_input(iframe_c, Filename,(*iinputframe), NULL);
 - if (nRet != 0)
 - {
 - av_strerror(nRet, szError, 256);
 - printf(szError);
 - printf("\n");
 - printf("Call avformat_open_input function failed!\n");
 - return 0;
 - }
 - if (av_find_stream_info(*iframe_c) < 0)
 - {
 - printf("Call av_find_stream_info function failed!\n");
 - return 0;
 - }
 - //输出视频信息
 - av_dump_format(*iframe_c, -1, Filename, 0);
 - //添加音频信息到输出context
 - for (i = 0; i < (*iframe_c)->nb_streams; i++)
 - {
 - if ((*iframe_c)->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 - {
 - video_stream_idx = i;
 - m_dwWidth = (*iframe_c)->streams[i]->codec->width;
 - m_dwHeight = (*iframe_c)->streams[i]->codec->height;
 - m_dbFrameRate = av_q2d((*iframe_c)->streams[i]->r_frame_rate);
 - video_codecID = (*iframe_c)->streams[i]->codec->codec_id;
 - video_pixelfromat = (*iframe_c)->streams[i]->codec->pix_fmt;
 - spspps_size = (*iframe_c)->streams[i]->codec->extradata_size;
 - memcpy(spspps,(*iframe_c)->streams[i]->codec->extradata,spspps_size);
 - }
 - else if ((*iframe_c)->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 - {
 - audio_stream_idx = i;
 - m_dwChannelCount = (*iframe_c)->streams[i]->codec->channels;
 - switch ((*iframe_c)->streams[i]->codec->sample_fmt)
 - {
 - case AV_SAMPLE_FMT_U8:
 - m_dwBitsPerSample = 8;
 - break;
 - case AV_SAMPLE_FMT_S16:
 - m_dwBitsPerSample = 16;
 - break;
 - case AV_SAMPLE_FMT_S32:
 - m_dwBitsPerSample = 32;
 - break;
 - default:
 - break;
 - }
 - m_dwFrequency = (*iframe_c)->streams[i]->codec->sample_rate;
 - audio_codecID = (*iframe_c)->streams[i]->codec->codec_id;
 - audio_frame_size = (*iframe_c)->streams[i]->codec->frame_size;
 - }
 - }
 - return 1;
 - }
 - int InitOutput()
 - {
 - int i = 0;
 - /* allocate the output media context */
 - avformat_alloc_output_context2(&oc, NULL, "flv", OUTPUTURL);
 - if (!oc)
 - {
 - return getchar();
 - }
 - ofmt = oc->oformat;
 - /* open the output file, if needed */
 - if (!(ofmt->flags & AVFMT_NOFILE))
 - {
 - if (avio_open(&oc->pb, OUTPUTURL, AVIO_FLAG_WRITE) < 0)
 - {
 - printf("Could not open '%s'\n", OUTPUTURL);
 - return getchar();
 - }
 - }
 - //添加音频信息到输出context
 - if(audio_stream_idx != -1)
 - {
 - ofmt->audio_codec = audio_codecID;
 - audio_st = Add_output_stream_2(oc, AVMEDIA_TYPE_AUDIO,audio_codecID,&audio_codec);
 - }
 - //添加视频信息到输出context
 - ofmt->video_codec = video_codecID;
 - video_st = Add_output_stream_2(oc, AVMEDIA_TYPE_VIDEO,video_codecID,&video_codec);
 - if (OpenCodec(video_st,video_codec) < 0) //打开视频编码器
 - {
 - printf("can not open video codec\n");
 - return getchar();
 - }
 - if(audio_stream_idx != -1)
 - {
 - if (OpenCodec(audio_st,audio_codec) < 0) //打开音频编码器
 - {
 - printf("can not open audio codec\n");
 - return getchar();
 - }
 - }
 - av_dump_format(oc, 0, OUTPUTURL, 1);
 - if (avformat_write_header(oc, NULL))
 - {
 - printf("Call avformat_write_header function failed.\n");
 - return 0;
 - }
 - if(audio_stream_idx != -1)
 - {
 - if ((strstr(oc->oformat->name, "flv") != NULL) ||
 - (strstr(oc->oformat->name, "mp4") != NULL) ||
 - (strstr(oc->oformat->name, "mov") != NULL) ||
 - (strstr(oc->oformat->name, "3gp") != NULL))
 - {
 - if (audio_st->codec->codec_id == AV_CODEC_ID_AAC) //AV_CODEC_ID_AAC
 - {
 - vbsf_aac_adtstoasc = av_bitstream_filter_init("aac_adtstoasc");
 - }
 - }
 - }
 - if(vbsf_aac_adtstoasc == NULL)
 - {
 - return -1;
 - }
 - return 1;
 - }
 - AVStream * Add_output_stream_2(AVFormatContext* output_format_context,AVMediaType codec_type_t, AVCodecID codecID,AVCodec **codec)
 - {
 - AVCodecContext* output_codec_context = NULL;
 - AVStream * output_stream = NULL;
 - /* find the encoder */
 - *codec = avcodec_find_encoder(codecID);
 - if (!(*codec))
 - {
 - return NULL;
 - }
 - output_stream = avformat_new_stream(output_format_context, *codec);
 - if (!output_stream)
 - {
 - return NULL;
 - }
 - output_stream->id = output_format_context->nb_streams - 1;
 - output_codec_context = output_stream->codec;
 - output_codec_context->codec_id = codecID;
 - output_codec_context->codec_type = codec_type_t;
 - switch (codec_type_t)
 - {
 - case AVMEDIA_TYPE_AUDIO:
 - AVRational CodecContext_time_base;
 - CodecContext_time_base.num = 1;
 - CodecContext_time_base.den = m_dwFrequency;
 - output_stream->time_base = CodecContext_time_base;
 - output_codec_context->time_base = CodecContext_time_base;
 - output_stream->start_time = 0;
 - output_codec_context->sample_rate = m_dwFrequency;
 - output_codec_context->channels = m_dwChannelCount;
 - output_codec_context->frame_size = audio_frame_size;
 - switch (m_dwBitsPerSample)
 - {
 - case 8:
 - output_codec_context->sample_fmt = AV_SAMPLE_FMT_U8;
 - break;
 - case 16:
 - output_codec_context->sample_fmt = AV_SAMPLE_FMT_S16;
 - break;
 - case 32:
 - output_codec_context->sample_fmt = AV_SAMPLE_FMT_S32;
 - break;
 - default:
 - break;
 - }
 - output_codec_context->block_align = 0;
 - if(! strcmp( output_format_context-> oformat-> name, "mp4" ) ||
 - !strcmp (output_format_context ->oformat ->name , "mov" ) ||
 - !strcmp (output_format_context ->oformat ->name , "3gp" ) ||
 - !strcmp (output_format_context ->oformat ->name , "flv" ))
 - {
 - output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
 - }
 - break;
 - case AVMEDIA_TYPE_VIDEO:
 - AVRational r_frame_rate_t;
 - r_frame_rate_t.num = 1000;
 - r_frame_rate_t.den = (int)(m_dbFrameRate * 1000);
 - output_stream->time_base = r_frame_rate_t;
 - output_codec_context->time_base = r_frame_rate_t;
 - AVRational r_frame_rate_s;
 - r_frame_rate_s.num = (int)(m_dbFrameRate * 1000);
 - r_frame_rate_s.den = 1000;
 - output_stream->r_frame_rate = r_frame_rate_s;
 - output_stream->start_time = 0;
 - output_codec_context->pix_fmt = video_pixelfromat;
 - output_codec_context->width = m_dwWidth;
 - output_codec_context->height = m_dwHeight;
 - output_codec_context->extradata = (uint8_t *)spspps;
 - output_codec_context->extradata_size = spspps_size;
 - //这里注意不要加头,demux的时候 h264filter过滤器会改变文件本身信息
 - //这里用output_codec_context->extradata 来显示缩略图
 - //if(! strcmp( output_format_context-> oformat-> name, "mp4" ) ||
 - // !strcmp (output_format_context ->oformat ->name , "mov" ) ||
 - // !strcmp (output_format_context ->oformat ->name , "3gp" ) ||
 - // !strcmp (output_format_context ->oformat ->name , "flv" ))
 - //{
 - // output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
 - //}
 - break;
 - default:
 - break;
 - }
 - return output_stream;
 - }
 - int OpenCodec(AVStream * istream, AVCodec * icodec)
 - {
 - AVCodecContext *c = istream->codec;
 - nRet = avcodec_open2(c, icodec, NULL);
 - return nRet;
 - }
 - int UintInput()
 - {
 - /* free the stream */
 - av_free(icodec);
 - return 1;
 - }
 - int UintOutput()
 - {
 - int i = 0;
 - nRet = av_write_trailer(oc);
 - if (nRet < 0)
 - {
 - av_strerror(nRet, szError, 256);
 - printf(szError);
 - printf("\n");
 - printf("Call av_write_trailer function failed\n");
 - }
 - if (vbsf_aac_adtstoasc !=NULL)
 - {
 - av_bitstream_filter_close(vbsf_aac_adtstoasc);
 - vbsf_aac_adtstoasc = NULL;
 - }
 - av_dump_format(oc, -1, OUTPUTURL, 1);
 - /* Free the streams. */
 - for (i = 0; i < oc->nb_streams; i++)
 - {
 - av_freep(&oc->streams[i]->codec);
 - av_freep(&oc->streams[i]);
 - }
 - if (!(ofmt->flags & AVFMT_NOFILE))
 - {
 - /* Close the output file. */
 - avio_close(oc->pb);
 - }
 - av_free(oc);
 - return 1;
 - }
 - void read_frame(AVFormatContext *oc)
 - {
 - int ret = 0;
 - ret = av_read_frame(icodec, &pkt);
 - if (pkt.stream_index == video_stream_idx)
 - {
 - write_frame_3(oc,VEDIO_ID,pkt);
 - }
 - else if (pkt.stream_index == audio_stream_idx)
 - {
 - write_frame_3(oc,AUDIO_ID,pkt);
 - }
 - }
 - void write_frame_3(AVFormatContext *oc,int ID,AVPacket pkt_t)
 - {
 - int64_t pts = 0, dts = 0;
 - int nRet = -1;
 - AVRational time_base_t;
 - time_base_t.num = 1;
 - time_base_t.den = 1000;
 - if(ID == VEDIO_ID)
 - {
 - AVPacket videopacket_t;
 - av_init_packet(&videopacket_t);
 - if (av_dup_packet(&videopacket_t) < 0)
 - {
 - av_free_packet(&videopacket_t);
 - }
 - videopacket_t.pts = pkt_t.pts;
 - videopacket_t.dts = pkt_t.dts;
 - videopacket_t.pos = 0;
 - videopacket_t.priv = 0;
 - videopacket_t.flags = 1;
 - videopacket_t.convergence_duration = 0;
 - videopacket_t.side_data_elems = 0;
 - videopacket_t.stream_index = VEDIO_ID;
 - videopacket_t.duration = 0;
 - videopacket_t.data = pkt_t.data;
 - videopacket_t.size = pkt_t.size;
 - nRet = av_interleaved_write_frame(oc, &videopacket_t);
 - if (nRet != 0)
 - {
 - printf("error av_interleaved_write_frame _ video\n");
 - }
 - av_free_packet(&videopacket_t);
 - }
 - else if(ID == AUDIO_ID)
 - {
 - AVPacket audiopacket_t;
 - av_init_packet(&audiopacket_t);
 - if (av_dup_packet(&audiopacket_t) < 0)
 - {
 - av_free_packet(&audiopacket_t);
 - }
 - audiopacket_t.pts = pkt_t.pts;
 - audiopacket_t.dts = pkt_t.dts;
 - audiopacket_t.pos = 0;
 - audiopacket_t.priv = 0;
 - audiopacket_t.flags = 1;
 - audiopacket_t.duration = 0;
 - audiopacket_t.convergence_duration = 0;
 - audiopacket_t.side_data_elems = 0;
 - audiopacket_t.stream_index = AUDIO_ID;
 - audiopacket_t.duration = 0;
 - audiopacket_t.data = pkt_t.data;
 - audiopacket_t.size = pkt_t.size;
 - //添加过滤器
 - if(! strcmp( oc-> oformat-> name, "mp4" ) ||
 - !strcmp (oc ->oformat ->name , "mov" ) ||
 - !strcmp (oc ->oformat ->name , "3gp" ) ||
 - !strcmp (oc ->oformat ->name , "flv" ))
 - {
 - if (audio_st->codec->codec_id == AV_CODEC_ID_AAC)
 - {
 - if (vbsf_aac_adtstoasc != NULL)
 - {
 - AVPacket filteredPacket = audiopacket_t;
 - int a = av_bitstream_filter_filter(vbsf_aac_adtstoasc,
 - audio_st->codec, NULL,&filteredPacket.data, &filteredPacket.size,
 - audiopacket_t.data, audiopacket_t.size, audiopacket_t.flags & AV_PKT_FLAG_KEY);
 - if (a > 0)
 - {
 - av_free_packet(&audiopacket_t);
 - filteredPacket.destruct = av_destruct_packet;
 - audiopacket_t = filteredPacket;
 - }
 - else if (a == 0)
 - {
 - audiopacket_t = filteredPacket;
 - }
 - else if (a < 0)
 - {
 - fprintf(stderr, "%s failed for stream %d, codec %s",
 - vbsf_aac_adtstoasc->filter->name,audiopacket_t.stream_index,audio_st->codec->codec ? audio_st->codec->codec->name : "copy");
 - av_free_packet(&audiopacket_t);
 - }
 - }
 - }
 - }
 - nRet = av_interleaved_write_frame(oc, &audiopacket_t);
 - if (nRet != 0)
 - {
 - printf("error av_interleaved_write_frame _ audio\n");
 - }
 - av_free_packet(&audiopacket_t);
 - }
 - }
 - int Es2Mux_2()
 - {
 - for (;;)
 - {
 - read_frame(oc);
 - }
 - return 1;
 - }
 
- //main.cpp
 - #include "ffmpeg.h"
 - int main(int argc ,char ** argv)
 - {
 - av_register_all();
 - avformat_network_init();
 - InitInput(INPUTURL,&icodec,&ifmt);
 - InitOutput();
 - printf("--------程序运行开始----------\n");
 - //////////////////////////////////////////////////////////////////////////
 - Es2Mux_2();
 - //////////////////////////////////////////////////////////////////////////
 - UintOutput();
 - UintInput();
 - printf("--------程序运行结束----------\n");
 - printf("-------请按任意键退出---------\n");
 - return getchar();
 - }
 
ffmpeg处理rtmp/文件/rtsp的推流和拉流的更多相关文章
- iOS开发之利用IJKPlayer+nginx+rtmp搭建直播的推流和拉流
		
最近项目中想实现直播的功能,所以研究了一段时间的直播功能,当然也是在别人的基础上不断的学习实现的,所以记录一下,希望对大家有所帮助. 直播拉流功能: 这里使用了开源的IJKPlayer第三框架,ijk ...
 - Mac上搭建直播服务器Nginx+rtmp,实现手机推流、拉流
		
转载自http://www.cnblogs.com/jys509/p/5649066.html 简介 nginx是非常优秀的开源服务器,用它来做hls或者rtmp流媒体服务器是非常不错的选择,本人在网 ...
 - 流媒体压力测试rtmp&hls(含推流和拉流)
		
http://blog.csdn.net/sinat_34194127/article/details/50816045 [root@localhost ~]# yum install git unz ...
 - java封装FFmpeg命令,支持原生ffmpeg全部命令,实现FFmpeg多进程处理与多线程输出控制(开启、关闭、查询),rtsp/rtmp推流、拉流
		
前言: 之前已经对FFmpeg命令进行了封装http://blog.csdn.net/eguid_1/article/details/51787646,但是当时没有考虑到扩展性,所以总体设计不是太好, ...
 - nginx+ffmpeg搭建rtmp转播rtsp流的flash服务器
		
本文概要: nginx是非常优秀的开源服务器,用它来做hls或者rtmp流媒体服务器是非常不错的选择.本文介绍了一种简易方法快速搭建rtmp流媒体服务器,也叫rtsp转播,数据源不是读取文件,而是采用 ...
 - 用FFmpeg+nginx+rtmp搭建环境实现推流
		
Windows: 1.下载文件: 链接:https://pan.baidu.com/s/1c2LmIHHw-dwLOlRN6iTIMg 提取码:g7sj 2.解压文件: 解压到nginx-1.7.11 ...
 - 三、Windows下用FFmpeg+nginx+rtmp搭建直播环境 实现推流、拉流
		
一.环境 1.开发环境:windows 2.开发工具:FFmpeg.nginx.nginx-rmtp-module (链接:https://pan.baidu.com/s/119d2GeMzddas_ ...
 - 推流和拉流的概念以及RTMP和HLS协议
		
推流为将直播内容推送至服务器的过程:拉流为服务器已有直播内容,用指定地址进行拉取的过程. rtmp rtmp是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写. ...
 - 开源流媒体服务器SRS学习笔记(1) - 安装、推流、拉流
		
SRS(Simple RTMP Server) 是国人写的一款非常优秀的开源流媒体服务器软件,可用于直播/录播/视频客服等多种场景,其定位是运营级的互联网直播服务器集群. 一.安装 官网提供了3种安 ...
 
随机推荐
- android-support-v4.jar异常解决方法
			
1.当一个项目引入其他library项目时,会出现android-support-v4.jar冲突问题: 解决:将library项目中的android-support-v4.jar更新到最新,方法右键 ...
 - mysql主从:主键冲突问题
			
1.检查从库 show slave status \G; Slave_IO_Running: YesSlave_SQL_Running: No 2.出现类似如下的报错: Last_SQL_Error: ...
 - 在Linux先显示文件
			
cat:从第一行开始显示文件内容. tac:从最后一行开始显示内容. nl:显示的时候带行号. more:一页一页显示. less:同more,可以向上翻页. head:显示文件前几行. head - ...
 - 修改Jmeter配置使能支持更大并发
			
Jmeter做并发测试时,报错 java.lang.OutOfMemoryError:gc overhead limit exceeded. 原因是jmeter默认分配内存的参数很小,256M吧.故而 ...
 - 【BZOJ1513】[POI2006]Tet-Tetris 3D 二维线段树
			
[BZOJ1513][POI2006]Tet-Tetris 3D Description Task: Tetris 3D "Tetris" 游戏的作者决定做一个新的游戏, 一个三维 ...
 - ArcGIS API for javascript Bookmarks(书签)示例2
			
1.运行效果图 说明:这篇博文介绍的书签位于地图之上 有关博文中引用的API文件 怎么iis上部署,请参考我前面的博文 2.HTML代码 <!DOCTYPE html> <html ...
 - python解释器安装教程
			
1. 首先,打开python的官网:python.org 2. 首页downloads下打开, 3. 最上边是两个最新的版本,长期计划,推荐使用python3,如果长期打算用p3,默认使用最新版本.如 ...
 - java的小知识点
			
1 获取当前路径 System.getProperty("user.dir") System.getProperty()参数大全# java.version ...
 - Numerical Differentiation 数值微分
			
zh.wikipedia.org/wiki/數值微分 数值微分是数值方法中的名词,是用函数的值及其他已知资讯来估计一函数导数的算法. http://mathworld.wolfram.com/Nume ...
 - 为什么要对url进行encode
			
发现现在几乎所有的网站都对url中的汉字和特殊的字符,进行了urlencode操作,也就是: http://hi.baidu.com/%BE%B2%D0%C4%C0%CF%C8%CB/creat/bl ...