// PlayVideo.cpp : Defines the entry point for the console application.
// extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <libavutil/avstring.h>
#include <libavutil/pixfmt.h>
#include <libavutil/log.h>
};
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <SDL.h>
#include <SDL_thread.h>
#include <SDL_main.h> #pragma comment(lib, "libmingwex.lib")
#pragma comment(lib, "libgcc.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib") #pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib") //speedloss is decided by scale
//#define PICTURE_W 640
//#define PICTURE_H 352
//#define PICTURE_PW 640
//#define PICTURE_PH 352
//change 100
#define MAX_QUEUE_SIZE 50 #define VIDEO_PICTURE_QUEUE_SIZE 2 typedef struct VideoPicture_t{
SDL_Overlay *bmp;
double pts;
double duration;
int width,height;
}VideoPicture; struct play_info_t{
//先注释掉同步
double audio_clock;//解码时钟
double audio_current_pts;//当前音频的pts
double vedio_clock;//解码时钟
double last_frame_pts;//上一帧的PTS值
double last_frame_delay;//上一帧的延时
double frame_timer; AVCodecContext *pVideoCodecCtx;
AVCodecContext *pAudioCodecCtx; VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex;
SDL_mutex *pictq_mutex;
SDL_cond *pictq_cond; struct SwrContext *audio_conv;
struct SwsContext *video_conv;
}; struct play_info_t g_play_info; typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
SDL_mutex *mutex;
SDL_cond *cond;
} PacketQueue; PacketQueue audio_queue;
PacketQueue video_queue;
int quit = 0;
SDL_Surface *screen;
SDL_Overlay *bmp;
SDL_Rect rect; int global_video_pkt_pts=0;
int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) {
int ret = avcodec_default_get_buffer(c, pic);
uint64_t *pts = (uint64_t *)av_malloc(sizeof(uint64_t));
*pts = global_video_pkt_pts;
pic->opaque = pts;
return ret;
}
void our_release_buffer(struct AVCodecContext *c, AVFrame *pic) {
if(pic) av_freep(&pic->opaque);
avcodec_default_release_buffer(c, pic);
} double get_audio_clock(void)
{
return g_play_info.audio_current_pts;
} double get_video_clock(void)
{
return g_play_info.vedio_clock;
} void picture_queque_init(struct play_info_t *play)
{
int i;
play->pictq_cond=SDL_CreateCond();
play->pictq_mutex=SDL_CreateMutex();
play->pictq_rindex=play->pictq_windex=0;
play->pictq_size=0;
memset(play->pictq,0,sizeof(play->pictq));
for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE;i++){ //注释掉 g_play_info.pVideoCodecCtx->height
//play->pictq[i].bmp=SDL_CreateYUVOverlay(PICTURE_W,PICTURE_H,SDL_YUY2_OVERLAY,screen);
play->pictq[i].bmp=SDL_CreateYUVOverlay(g_play_info.pVideoCodecCtx->width,g_play_info.pVideoCodecCtx->height,SDL_YUY2_OVERLAY,screen);
}
} void picture_queque_destroy(struct play_info_t *play)
{
int i;
for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE;i++){
SDL_FreeYUVOverlay(play->pictq[i].bmp);
}
} void packet_queue_init(PacketQueue *q) {
memset(q, 0, sizeof(PacketQueue));
q->mutex = SDL_CreateMutex();
q->cond = SDL_CreateCond();
} int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
AVPacketList *pkt1;
if(av_dup_packet(pkt) < 0) {
return -1;
}
pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList));
if (!pkt1)
return -1;
pkt1->pkt = *pkt;
pkt1->next = NULL;
SDL_LockMutex(q->mutex);
if (!q->last_pkt)
q->first_pkt = pkt1;
else
q->last_pkt->next = pkt1;
q->last_pkt = pkt1;
q->nb_packets++;
q->size += pkt1->pkt.size;
SDL_CondSignal(q->cond);
SDL_UnlockMutex(q->mutex);
return 0;
} static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {
AVPacketList *pkt1;
int ret;
SDL_LockMutex(q->mutex);
for(;;) {
if(quit) {
ret = -1;
break;
}
pkt1 = q->first_pkt;
if (pkt1) {
q->first_pkt = pkt1->next;
if (!q->first_pkt)
q->last_pkt = NULL;
q->nb_packets--;
q->size -= pkt1->pkt.size;
*pkt = pkt1->pkt;
av_free(pkt1);
ret = 1;
break;
} else if (!block) {
ret = 0;
break;
} else {
SDL_CondWait(q->cond, q->mutex);
}
}
SDL_UnlockMutex(q->mutex);
return ret;
} int decode_interrupt_cb(void) {
return quit;
} //计算正确的pts值
double sync_video(struct play_info_t *play,AVFrame* frame,double pts)
{
double frame_delay;
if(pts!=0)
play->vedio_clock=pts;
else
pts=play->vedio_clock;
frame_delay=av_q2d(play->pVideoCodecCtx->time_base);//一帧占用的时间
frame_delay+=frame->repeat_pict*(frame_delay*0.5);//计算重复帧
play->vedio_clock+=frame_delay;
return pts;
} int audio_decode_frame(struct play_info_t* play, uint8_t *audio_buf,int buf_size) {
AVCodecContext *aCodecCtx=play->pAudioCodecCtx;
AVFrame *pAudioFrame=avcodec_alloc_frame();
AVPacket pkt,pkt1;
int frame_finished=0;
int pkt_pos,pkt_len;
int src_len=0,dst_len=0,data_size=0;
float pts=0;
avcodec_get_frame_defaults(pAudioFrame); uint8_t *out[]={audio_buf}; for(;!quit;){
if(packet_queue_get(&audio_queue, &pkt, 1) < 0) {
av_free(pAudioFrame);
return -1;
}
pkt1=pkt;
pkt_pos=0;
pkt_len=pkt.size; while(pkt_pos<pkt.size && !quit){
if((src_len=avcodec_decode_audio4(aCodecCtx,pAudioFrame,&frame_finished,&pkt1))<0){
av_free_packet(&pkt);
av_free(pAudioFrame);
return -1;
} /* play->audio_clock+=(double)(pAudioFrame->linesize[0])/
(aCodecCtx->channels*aCodecCtx->sample_rate*av_get_bytes_per_sample(aCodecCtx->sample_fmt)); */
if(video_queue.nb_packets>= 100 || audio_queue.nb_packets>= 200){ //改写
//printf("%d---%d\n",video_queue.nb_packets,audio_queue.nb_packets);
Sleep(20); // change 10000 }
else if(video_queue.nb_packets>= 50 || audio_queue.nb_packets>= 100)
{
Sleep(10); } if(frame_finished){
const uint8_t **in=(const uint8_t **)pAudioFrame->data;
int len=swr_convert(play->audio_conv,out,buf_size/aCodecCtx->channels/av_get_bytes_per_sample(AV_SAMPLE_FMT_S16),
in,pAudioFrame->linesize[0]/aCodecCtx->channels/av_get_bytes_per_sample((AVSampleFormat)pAudioFrame->format));
len=len*aCodecCtx->channels*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
av_free(pAudioFrame);
av_free_packet(&pkt);
return len;
}else{
if (!pkt1.data && aCodecCtx->codec->capabilities & CODEC_CAP_DELAY){
break;
}
}
pkt_pos+=src_len;//已经解码的长度
pkt1.data=pkt.data+pkt_pos;
pkt1.size=pkt.size-pkt_pos; }
av_free_packet(&pkt);
}
av_free(pAudioFrame);
return dst_len;
} //decode the audio data ,and copy the result to stream
void SDLCALL audio_callback(void *userdata, Uint8 *stream, int len)
{
struct play_info_t *play=(struct play_info_t*)userdata;
AVCodecContext *aCodecCtx = play->pAudioCodecCtx;
int len1, audio_size;
static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
static unsigned int audio_buf_size = 0;
static unsigned int audio_buf_index = 0;
int bytes_per_sec=2*aCodecCtx->channels*aCodecCtx->sample_rate; while(len > 0 && !quit) {
if(audio_buf_index >= audio_buf_size) {
audio_size = audio_decode_frame(play, audio_buf,sizeof(audio_buf));
if(audio_size < 0) {
audio_buf_size = 1024;
memset(audio_buf, 0, audio_buf_size);
} else {
audio_buf_size = audio_size;
}
audio_buf_index = 0;
}
len1 = audio_buf_size - audio_buf_index; if(len1 > len)
len1 = len;
memcpy(stream, (uint8_t *)audio_buf + audio_buf_index, len1);
len -= len1;
stream += len1;
audio_buf_index += len1;
}
//先注释掉同步,自然播放
if(audio_buf_size > audio_buf_index){
play->audio_current_pts=play->audio_clock-((double)(audio_buf_size-audio_buf_index)/(double)bytes_per_sec);
if(play->audio_current_pts<0)
play->audio_current_pts=play->audio_clock;
printf("audio-pts:%f\n",play->audio_current_pts);
}
} int SDLCALL video_decode_callback(void* arg)
{
printf("---in video decode thread ---\n");
struct play_info_t* play=(struct play_info_t*)arg;
AVCodecContext *pVideoCodecCtx=play->pVideoCodecCtx;
double pts;
VideoPicture *vp;
AVPacket pkt;
int frame_finished;
AVPicture pict = { { 0 } };
AVFrame *pVideoFrame=avcodec_alloc_frame();
if(pVideoFrame==NULL){
printf("can't alloc video frame!\n");
return -1;
} while(!quit){
if(packet_queue_get(&video_queue, &pkt, 1) < 0) {
return -1;
}
pts = 0;
// Save global pts to be stored in pFrame in first call
global_video_pkt_pts = pkt.pts;
avcodec_decode_video2(pVideoCodecCtx,pVideoFrame,&frame_finished,&pkt);
if(pkt.dts == AV_NOPTS_VALUE && pVideoFrame->opaque && *(uint64_t*)pVideoFrame->opaque != AV_NOPTS_VALUE){
pts = *(uint64_t *)pVideoFrame->opaque;
} else if(pkt.dts!=AV_NOPTS_VALUE){
pts=pkt.dts;
}else{
pts=0;
}
pts*=av_q2d(pVideoCodecCtx->time_base); av_free_packet(&pkt);
if(video_queue.nb_packets>= 100 || audio_queue.nb_packets>= 200){ //改写
printf("%d---%d\n",video_queue.nb_packets,audio_queue.nb_packets);
Sleep(20); // change 10000 }
else if(video_queue.nb_packets>= 50 || audio_queue.nb_packets>= 100)
{
Sleep(10); }
if(frame_finished){
SDL_LockMutex(play->pictq_mutex);
while(play->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !quit){
SDL_CondWait(play->pictq_cond,play->pictq_mutex);
}
SDL_UnlockMutex(play->pictq_mutex);
if(quit)
goto out; vp=&play->pictq[play->pictq_windex];
SDL_Overlay *bmp=vp->bmp; //定义
//序列化帧
pts=sync_video(&g_play_info,pVideoFrame,pts);
vp->pts=pts;
printf("video-pts:%f\n",pts); SDL_LockYUVOverlay(bmp); //加锁
pict.data[0]=bmp->pixels[0];
pict.data[1]=bmp->pixels[2];
pict.data[2]=bmp->pixels[1];
pict.linesize[0]=bmp->pitches[0];
pict.linesize[1]=bmp->pitches[2];
pict.linesize[2]=bmp->pitches[1];
sws_scale(play->video_conv,pVideoFrame->data,pVideoFrame->linesize,0,
pVideoFrame->height,pict.data,pict.linesize);
SDL_UnlockYUVOverlay(bmp); play->pictq_windex=(play->pictq_windex+1)%VIDEO_PICTURE_QUEUE_SIZE;
SDL_LockMutex(play->pictq_mutex);
play->pictq_size++;
SDL_UnlockMutex(play->pictq_mutex); }
}
out:
av_free(pVideoFrame);
printf("---- exit video_decode_callback ----\n");
return 0;
} void video_image_display(struct play_info_t *play)
{
double delay,time;
VideoPicture *vp;
double diff,sync_threshold;
if(play->pictq_size>0){
vp=&play->pictq[play->pictq_rindex];
delay=vp->pts - play->last_frame_pts;
if(delay>0 && delay<10){
play->last_frame_delay=delay;
}
delay=play->last_frame_delay; diff=vp->pts-get_audio_clock();
sync_threshold = FFMAX(0.01, delay);
if (fabs(diff) < 10) {
if (diff <= -sync_threshold)
delay = 0;
else if (diff >= sync_threshold)
delay = 2 * delay;
} time=av_gettime()/1000000.0;
if(time < play->frame_timer+delay)
return ; if(delay>0)
play->frame_timer+=delay;
play->last_frame_pts=vp->pts; SDL_DisplayYUVOverlay(vp->bmp,&rect); //显示 play->pictq_rindex=(play->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE; SDL_LockMutex(play->pictq_mutex);
play->pictq_size--;
SDL_CondSignal(play->pictq_cond);
SDL_UnlockMutex(play->pictq_mutex); }
} int SDLCALL video_show_callback(void* arg)
{
double delay=80;
struct play_info_t *play=(struct play_info_t*)arg;
while(!quit){
video_image_display(play);
Sleep(delay);
}
printf("----exit video_show_callback ----\n");
return 0;
} void player_log_callback(void* ptr, int level, const char* fmt, va_list vl)
{
static int print_prefix = 0;
static int count;
char line[1024];
av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);
printf("%s",line);
} int main(int argc,char *argv[])
{
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)<0){
printf("Init SDL err!\n");
return -1;
} av_log_set_callback(player_log_callback);
av_register_all(); AVFormatContext *pFormatCtx;
pFormatCtx=avformat_alloc_context();
argv[1]="test.mp4";
if(avformat_open_input(&pFormatCtx,argv[1],NULL,NULL)<0){
printf("avformat_open_input err!\n");
return -1;
} if(avformat_find_stream_info(pFormatCtx,NULL)<0){
printf("avformat_find_stream_info err!\n");
return -1;
} //av_dump_format(pFormatCtx,0,argv[1],0); int video_stream=-1,audio_stream=-1,i;
for(i=0;i<pFormatCtx->nb_streams;i++){
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
video_stream=i;
}
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
audio_stream=i;
}
}
if(video_stream==-1 || audio_stream==-1){
printf("not find video or audio stream!\n");
avformat_close_input(&pFormatCtx);
return -1;
}
g_play_info.pVideoCodecCtx=pFormatCtx->streams[video_stream]->codec;
g_play_info.pAudioCodecCtx=pFormatCtx->streams[audio_stream]->codec; //find the decoder
AVCodec *pVideoCodec=avcodec_find_decoder(g_play_info.pVideoCodecCtx->codec_id);
if(pVideoCodec==NULL){
printf("not find video decoder!\n");
avformat_close_input(&pFormatCtx);
return -1;
}
AVCodec *pAudioCodec=avcodec_find_decoder(g_play_info.pAudioCodecCtx->codec_id);
if(pVideoCodec==NULL){
printf("not find audio decoder!\n");
avformat_close_input(&pFormatCtx);
return -1;
}
//open the codec
if(avcodec_open(g_play_info.pVideoCodecCtx,pVideoCodec)<0){
printf("can't open the video decoder!\n");
avformat_close_input(&pFormatCtx);
return -1;
}
if(avcodec_open(g_play_info.pAudioCodecCtx,pAudioCodec)<0){
printf("can't open the audio decoder!\n");
avcodec_close(g_play_info.pVideoCodecCtx);
avformat_close_input(&pFormatCtx);
return -1;
} //setup SDL
screen = SDL_SetVideoMode(g_play_info.pVideoCodecCtx->width, g_play_info.pVideoCodecCtx->height, 0, 0);//设置视频模式参数
picture_queque_init(&g_play_info);
packet_queue_init(&video_queue);
packet_queue_init(&audio_queue); rect.x=0;
rect.y=0;
rect.w = g_play_info.pVideoCodecCtx->width;
rect.h = g_play_info.pVideoCodecCtx->height; //setup the sdl audio
SDL_AudioSpec sdl_audio;
int64_t wanted_channel_layout = 0;
int wanted_nb_channels;
wanted_channel_layout =
(g_play_info.pAudioCodecCtx->channel_layout &&
g_play_info.pAudioCodecCtx->channels == av_get_channel_layout_nb_channels(g_play_info.pAudioCodecCtx->channel_layout)) ? g_play_info.pAudioCodecCtx->channel_layout : av_get_default_channel_layout(g_play_info.pAudioCodecCtx->channels);
wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
/* SDL only supports 1, 2, 4 or 6 channels at the moment, so we have to make sure not to request anything else. */
while (wanted_nb_channels > 0 && (wanted_nb_channels == 3 || wanted_nb_channels == 5 || wanted_nb_channels > 6)) {
wanted_nb_channels--;
wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
}
sdl_audio.channels=av_get_channel_layout_nb_channels(wanted_channel_layout);
g_play_info.pAudioCodecCtx->channels=sdl_audio.channels;
g_play_info.pAudioCodecCtx->channel_layout=wanted_channel_layout; g_play_info.audio_conv=swr_alloc_set_opts(NULL,wanted_channel_layout,AV_SAMPLE_FMT_S16,g_play_info.pAudioCodecCtx->sample_rate,
wanted_channel_layout,g_play_info.pAudioCodecCtx->sample_fmt,
g_play_info.pAudioCodecCtx->sample_rate,0,NULL);
swr_init(g_play_info.audio_conv); sdl_audio.freq=g_play_info.pAudioCodecCtx->sample_rate;
sdl_audio.format=AUDIO_S16SYS;
sdl_audio.channels=g_play_info.pAudioCodecCtx->channels;
sdl_audio.silence=0;
sdl_audio.samples=1024;
sdl_audio.callback=audio_callback;//calls when the audio device need more data
sdl_audio.userdata=&g_play_info;
if(SDL_OpenAudio(&sdl_audio,NULL)<0){
printf("can't open audio device!\n");
goto err_alloc_frame1;
}
g_play_info.vedio_clock=0;
g_play_info.audio_clock=0;
g_play_info.audio_current_pts=0;
g_play_info.last_frame_pts=0;
g_play_info.last_frame_delay=0;
g_play_info.frame_timer=av_gettime()/1000000.0;
g_play_info.pVideoCodecCtx->get_buffer=our_get_buffer;
g_play_info.pVideoCodecCtx->release_buffer=our_release_buffer; SDL_PauseAudio(0);
g_play_info.video_conv=sws_getContext(g_play_info.pVideoCodecCtx->width,g_play_info.pVideoCodecCtx->height,
g_play_info.pVideoCodecCtx->pix_fmt,
g_play_info.pVideoCodecCtx->width,g_play_info.pVideoCodecCtx->height,PIX_FMT_YUYV422,SWS_POINT,NULL,NULL,NULL);
SDL_Thread * video_decode_thread=SDL_CreateThread(video_decode_callback,(void*)&g_play_info);
SDL_Thread * video_show_thread=SDL_CreateThread(video_show_callback,(void*)&g_play_info);
SDL_Event sdl_event;
AVPacket packet; while(!quit){
SDL_PollEvent(&sdl_event);
if(sdl_event.type==SDL_QUIT){
SDL_CondSignal(video_queue.cond);
SDL_CondSignal(audio_queue.cond);
quit=1;
break;
}
if(av_read_frame(pFormatCtx,&packet)<0){
quit=1;
continue;
}
if(packet.stream_ndex==video_stream){
packet_queue_put(&video_queue,&packet);
//change
Sleep(25);//change
}else if(packet.stream_index==audio_stream){
packet_queue_put(&audio_queue,&packet);
//change
}else{
av_free_packet(&packet);
} //usleep(5000);
}
SDL_CloseAudio();
SDL_CondSignal(g_play_info.pictq_cond);
SDL_WaitThread(video_decode_thread,NULL);
SDL_WaitThread(video_show_thread,NULL);
picture_queque_destroy(&g_play_info); swr_free(&g_play_info.audio_conv);
sws_freeContext(g_play_info.video_conv); SDL_FreeSurface(screen);
avcodec_close(g_play_info.pVideoCodecCtx);
avcodec_close(g_play_info.pAudioCodecCtx);
avformat_close_input(&pFormatCtx);
return 0; err_alloc_frame1:
avcodec_close(g_play_info.pAudioCodecCtx);
avcodec_close(g_play_info.pVideoCodecCtx);
avformat_close_input(&pFormatCtx);
return -1;
}

SDL播放视频的更多相关文章

  1. SDL的基础知识以及利用SDL播放视频

    原文地址:http://blog.csdn.net/i_scream_/article/details/52714378 此博文相关知识点从雷神的博客以及视频学习,截图也是用了他的课件, 雷神博客地址 ...

  2. vlc sdl 播放视频可随窗口改变大小

    #include <stdio.h> #include <stdint.h> #include <math.h> #include <stdlib.h> ...

  3. ffmpeg和opencv 播放视频文件和显示器

    ffmpeg它是基于最新版本,在官网下载http://ffmpeg.zeranoe.com/builds/.编译时VS2010配置相关头文件及库的路径就可以.opencv的搭建參考上一个博客. 首先简 ...

  4. MFC中使用SDL播放音频没有声音的解决方法

    本文所说的音频是指的纯音频,不包含视频的那种. 在控制台中使用SDL播放音频,一般情况下不会有问题. 但是在MFC中使用SDL播放音频的时候,会出现没有声音的情况.经过长时间探索,没有找到特别好的解决 ...

  5. SDL播放YUV----单帧

    用到的项目:Tocy-Android-SDLv2 C中的 入口: main.c as_lesson_XXX.c bmp_main : 在C中定义文件的路径: char *filepath = &quo ...

  6. AVAssetReader+AVAssetReaderTrackOutput播放视频

    该文章引用自:http://www.jianshu.com/p/3d5ccbde0de1 IOS 微信聊天发送小视频的秘密(AVAssetReader+AVAssetReaderTrackOutput ...

  7. Android实现播放视频

    转载:http://www.bdqn.cn/news/201311/12100.shtml 使用VideoView播放视频 VideoView,用于播放一段视频媒体,它继承了SurfaceView,位 ...

  8. Android使用TextureView播放视频

    1.引言 如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的TextureView做到. 1).TextureView的兄弟SurfaceView 应用 ...

  9. WPF播放视频

    在现在的项目中需要使用到播放视频的功能,本来打算使用VLC来做的.后来发现WPF 4.0之后新增了MediaElement类,可以实现视频播放. <Grid> <Grid.RowDe ...

随机推荐

  1. css隔行换色

    .tab1 tr:nth-of-type(odd){ background:#eeeeee;} .tab1 tr:nth-of-type(even){ background:#f8f8f8;} .ta ...

  2. Unity时钟定时器插件

    Unity时钟定时器插件 http://dsqiu.iteye.com/blog/2020603https://github.com/joserocha3/KillerCircles/blob/67a ...

  3. java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别

    java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别   以前一直没有注意过这个问题,前两天机缘巧合上网查了一下,然后自 ...

  4. 安装RabbitMQ遇到的问题

    消息队列RabbitMQ在安装的时候出现了问题.. 我这里是参考的 .NET 环境中使用RabbitMQ 进行安装的..首先声明 这篇博文没有问题.. 但是在我安装的时候发现..ErLang环境装完 ...

  5. Android Studio 连接真机不识别

    本人也是初学..写错的请大神多多批评指正! 不胜荣幸!! 强烈推荐使用真机测试..除非是最后关头要测试各个Android系统版本.. 本人遇到的连不上的原因有以下几种: 1  --   手机设置问题. ...

  6. 改变Vim在iTerm2中的光标

    vim ~/.vimrc 添加 " Change cursor shape between insert and normal mode in iTerm2.appif $TERM_PROG ...

  7. knockout-validation不自动插入错误消息

    <div data-bind="validationOptions:{insertMessages:false}"> <div class="valid ...

  8. 本地wampserver如何配置伪静态

    本地wamp实现虚拟主机后,我把自己的站放进去就出现了500错误看日志看到.htaccess: Invalid command ‘RewriteEngine’, perhaps misspelled ...

  9. BootStrap学习------栅格

    使用Bootstrap前端框架-栅格 要点 1.使用Bootstrap需要引入的css和js: (1)bootstrap.min.js (2)bootstrap.min.css 2.栅格系统需要通过& ...

  10. spring之BeanFactoryAware接口

    springBeanFactoryAware (转)要直接在自己的代码中读取spring的bean,我们除了根据常用的set外,也可以通过spring的BeanFactoryAware接口实现,只要实 ...