// 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. DX9资源管理

    http://www.cnblogs.com/cxrs/archive/2013/04/03/D3DResourceManager.html http://kasicass.blog.163.com/ ...

  2. jsp总结

    JSP 定义:    1)Java Server Page, Java EE 组件,本质上是 Servlet.    2)运行在 Web Container.接收 Http Request,生成 Ht ...

  3. Code First 关系 Fluent API

    通过实体框架 Code First,可以使用您自己的域类表示 EF 执行查询.更改跟踪和更新函数所依赖的模型.Code First 利用称为“约定先于配置”的编程模式.这意味着 Code First ...

  4. JavaScript 中 的prototype和__proto__

    1.prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象.它是显示修改对象的原型的属性. 2.__proto__是一个对象拥有的内置属性(请注 ...

  5. 在ASP.MVC中使用Ajax

    Asp.net MVC 抛弃了Asp.net WebForm那种高度封装的控件,让我们跟底层的HTML有了更多的亲近.可以更自由.更灵活的去控制HTML的结构.样式和行为.Asp.net MVC可以更 ...

  6. android自定义控件(7)-获取自定义ImageView的src属性

    创建一个自定义组件,继承 ImageView.在我的 xml 布局文件中是这样设置的: <Mycomponent android:src="@drawable/my_test_imag ...

  7. SQL Server2008窗口计算

    (一) 窗口的定义:指为用户指定的一组行,也称着"分区".如下图所示的窗口分区.每一个班级看作是一个数据窗口,一共有三个窗口 (二)窗口计算的相关方法 1)over()用法  格式 ...

  8. php后台多用户权限组思路与实现程序代码

    网站开发少不了有网站后台,有了后台自然要对用户有同角色来分配一下,特别是多用户系统的情况下,如我一个系统要有多个管理员,那么我这些管理要分成,编辑,友情连接,管理员等,那我们要有权限和角色分配,今天我 ...

  9. sql是如何执行一个查询的!

    引用自:http://rusanu.com/2013/08/01/understanding-how-sql-server-executes-a-query/ Understanding how SQ ...

  10. WCF--提示:"未找到终结点。"

    刚开始调用WCF的时候一直报错... ““System.ServiceModel.EndpointNotFoundException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进 ...