📄 avoutput.c
字号:
/********************************************** * Dawn Light Player * * avoutput.c * * Created by kf701 * 21:39:45 02/25/08 CST * * $Id: avoutput.c 174 2008-03-22 06:30:04Z kf701 $ **********************************************/#include "avcodec.h"#include "swscale.h"#include "avutil.h"#include "avformat.h"#include "avdecode.h"#include "avoutput.h"#include "avinput.h"#include "global.h"static AVPicture *logo_picture = NULL;static int init_logo_picture(void);static vo_t *gl_vo = NULL;static vo_t *first_vo = NULL;static ao_t *gl_ao = NULL;static ao_t *first_ao = NULL;#define REGISTER_VO(X, x) \ if( ENABLE_VO_##X ) \ { \ extern vo_t vo_##x; \ register_vo(&vo_##x); \ }#define REGISTER_AO(X, x) \ if( ENABLE_AO_##X ) \ { \ extern ao_t ao_##x; \ register_ao(&ao_##x); \ }static void register_vo(vo_t *vo){ vo_t **p; p = &first_vo; while (*p != NULL) p = &(*p)->next; *p = vo; vo->next = NULL;}static void register_ao(ao_t *ao){ ao_t **p; p = &first_ao; while (*p != NULL) p = &(*p)->next; *p = ao; ao->next = NULL;}vo_t *get_vo_by_name(const char *name){ vo_t *p; p = first_vo; while (p) { if (strcmp(name,p->name) == 0) return p; p = p->next; } return NULL;}ao_t *get_ao_by_name(const char *name){ ao_t *p; p = first_ao; while (p) { if (strcmp(name,p->name) == 0) return p; p = p->next; } return NULL;}void output_register_all(void){ REGISTER_VO(NULL, null); REGISTER_VO(SDL, sdl); REGISTER_VO(X11, x11); REGISTER_VO(FB, fb); REGISTER_VO(GL, gl); REGISTER_VO(DIRECTX, directx); REGISTER_AO(NULL, null); REGISTER_AO(ALSA, alsa); REGISTER_AO(OSS, oss); REGISTER_AO(SDL, sdl); REGISTER_AO(DSOUND, dsound);}queue_t *picture_queue = NULL;queue_t *samples_queue = NULL;int av_output_init(void){ av_log(NULL, AV_LOG_INFO, "*************INIT OUTPUT*************\n"); /*----------------------------------------------------------------------------- * audio and video queue new *-----------------------------------------------------------------------------*/ picture_queue = dlp_queue_new(); if ( NULL == picture_queue) { av_log(NULL,AV_LOG_ERROR,"video output picture queue init ERROR\n"); dlp_exit(-1); } av_log(NULL,AV_LOG_INFO,"video output picture queue init OK\n"); samples_queue = dlp_queue_new(); if ( NULL == samples_queue) { av_log(NULL,AV_LOG_ERROR,"audio output samples queue init ERROR\n"); dlp_exit(-1); } av_log(NULL,AV_LOG_INFO,"audio output samples queue init OK\n"); /*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------*/ output_register_all(); /*----------------------------------------------------------------------------- * select audio and video output *-----------------------------------------------------------------------------*/ gl_vo = get_vo_by_name(dlpctxp->vo); if ( NULL == gl_vo ) { av_log(NULL, AV_LOG_ERROR, "%s output NOT FOUND\n", dlpctxp->vo); dlp_exit(-1); } av_log(NULL, AV_LOG_INFO, "call %s vo_init now\n", gl_vo->name); if ( gl_vo->vo_init() < 0 ) dlp_exit(-1); if ( gl_vo->vo_event_loop ) dlp_main_loop = gl_vo->vo_event_loop; gl_ao = get_ao_by_name(dlpctxp->ao); if ( NULL == gl_ao ) { av_log(NULL, AV_LOG_ERROR, "%s output NOT FOUND\n", dlpctxp->ao); dlp_exit(-1); } av_log(NULL, AV_LOG_INFO, "call %s ao_init now\n", gl_ao->name); if ( gl_ao->ao_init() < 0 ) { av_log(NULL, AV_LOG_ERROR, "call %s ao_init error\n", gl_ao->name); dlp_exit(-1); } /*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------*/ if ( init_logo_picture() < 0 ) av_log(NULL, AV_LOG_ERROR, "init logo picture error\n"); av_log(NULL, AV_LOG_INFO, "*************INIT OUTPUT*************\n"); return 0;}int av_output_uninit(void){ if ( samples_queue ) { dlp_queue_free(samples_queue, (free_func)av_free_sample); samples_queue = NULL; } if ( picture_queue ) { dlp_queue_free(picture_queue, (free_func)avpicture_free); picture_queue = NULL; } if ( gl_vo ) { av_log(NULL, AV_LOG_INFO, "call %s vo_uninit now\n", gl_vo->name); gl_vo->vo_uninit(); } if ( gl_ao ) { av_log(NULL, AV_LOG_INFO, "call %s ao_uninit now\n", gl_ao->name); gl_ao->ao_uninit(); } return 0;}static int init_logo_picture(void){ int ret; AVPicture *pict; static struct SwsContext *img_convert_ctx; FILE *fp = fopen( "logo.yuv", "rb" ); if ( NULL == fp ) return -1; pict = av_mallocz(sizeof(AVPicture)); ret = avpicture_alloc(pict, 0, 320, 240); if ( -1 == ret ) { av_log(NULL, AV_LOG_ERROR, "av picture alloc err\n"); av_free(pict); return -1; } fread(pict->data[0], 1, 115200, fp); fclose(fp); logo_picture = av_mallocz(sizeof(AVPicture)); ret = avpicture_alloc(logo_picture, 0, dlpctxp->pwidth, dlpctxp->pheight); if ( -1 == ret ) { av_log(NULL, AV_LOG_ERROR, "av picture alloc err\n"); av_free(logo_picture); logo_picture = NULL; avpicture_free(pict); av_free(pict); return -1; } img_convert_ctx = sws_getCachedContext(img_convert_ctx, 320, 240, 0, dlpctxp->pwidth, dlpctxp->pheight, 0, SWS_BICUBIC, NULL, NULL, NULL); if (img_convert_ctx == NULL) { av_log(NULL, AV_LOG_ERROR, "Cannot initialize the conversion context\n"); avpicture_free(pict); av_free(pict); avpicture_free(logo_picture); av_free(logo_picture); logo_picture = NULL; return -1; } sws_scale(img_convert_ctx, pict->data, pict->linesize, 0, 240, logo_picture->data, logo_picture->linesize); avpicture_free(pict); av_free(pict); return 0;}/*----------------------------------------------------------------------------- * audio and video output thread *-----------------------------------------------------------------------------*/static void *audio_output_thread(void *arg){ AVSample *s; while (1) { if ( dlpctxp->paused ) { usleep(50*1000); continue; } s = dlp_queue_pop_head(samples_queue); if ( s ) { gl_ao->ao_play(s); /* MUST FREE sample here */ av_free_sample(s); av_free(s); dlpctxp->last_audio_pts = s->pts; } else dlp_wait_on_queue(samples_queue); } return 0;}static void *video_output_thread(void *arg){ AVPicture_t *picture; AVPicture *pic; int64_t pre_time, after_time; /* Control FPS */ int rest_time; int need_show_logo = 0; while (1) { if ( dlpctxp->paused ) { usleep(50*1000); continue; } pre_time = av_gettime(); picture = dlp_queue_pop_head(picture_queue); if ( picture ) { need_show_logo = 0; pic = (AVPicture*)picture; gl_vo->vo_display(pic); after_time = av_gettime(); rest_time = 1000*1000/dlpctxp->fps - (after_time - pre_time); if ( dlpctxp->last_audio_pts <= 0 || NULL == dlp_actxp || AO_ID_EXAMPLE == gl_ao->id ) { /* only video, need not sync AV */ goto not_sync_p; } if ( dlpctxp->last_audio_pts > picture->pts ) { rest_time = rest_time / 2; } else if ( dlpctxp->last_audio_pts < picture->pts ) { rest_time = rest_time * 2; }not_sync_p: if ( rest_time > 0 ) usleep(rest_time); /* MUST FREE picture here */ avpicture_free(pic); av_free(picture); } else { if ( need_show_logo > 5 && logo_picture ) gl_vo->vo_display(logo_picture); need_show_logo++; dlp_wait_on_queue_timeout(picture_queue, 500); } } return 0;}void create_avoutput_thread(void *arg){ pthread_t threadid; if ( pthread_create(&threadid, NULL, video_output_thread, NULL) ) { av_log(NULL, AV_LOG_ERROR, "video output thread start error\n"); } if ( pthread_create(&threadid, NULL, audio_output_thread, NULL) ) { av_log(NULL, AV_LOG_ERROR, "audio output thread start error\n"); } av_log(NULL, AV_LOG_INFO, "video output thread start\n"); av_log(NULL, AV_LOG_INFO, "audio output thread start\n");}/*----------------------------------------------------------------------------- * AV Sample functions *-----------------------------------------------------------------------------*/int av_new_sample(AVSample *s, int size){ s->data = av_malloc(size); s->size = size; return 0;}void av_free_sample(AVSample *s){ av_free(s->data); s->data = NULL; s->size = 0;}AVSample *av_dup_sample(AVSample *s){ AVSample *new; new = av_malloc( sizeof(AVSample) ); av_new_sample( new, s->size ); memcpy( new->data, s->data, s->size ); return new;}/*----------------------------------------------------------------------------- * User Interface functions *-----------------------------------------------------------------------------*/int dlp_add_volume(void){ return gl_ao->ao_control( AO_ADD_VOLUME, NULL );}int dlp_sub_volume(void){ return gl_ao->ao_control( AO_SUB_VOLUME, NULL );}int dlp_pause_ao(void){ return gl_ao->ao_control( AO_PAUSE, NULL );}int dlp_resume_ao(void){ return gl_ao->ao_control( AO_RESUME, NULL );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -