⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avdecode.c

📁 DawnLightPlayer,一个新的基于ffmpeg的全功能播放器
💻 C
字号:
/********************************************** * Dawn Light Player * *  avdecode.c * * Created by maddrone and kf701 * Mon Feb 25 17:05:41 CST 2008 * * $Id: avdecode.c 171 2008-03-21 08:00:10Z kf701 $ **********************************************/#include "avcodec.h"#include "swscale.h"#include "avformat.h"#include "avinput.h"#include "avoutput.h"#include "global.h"AVCodecContext dlp_vctx, dlp_actx;AVCodecContext *dlp_actxp = NULL, *dlp_vctxp = NULL;AVCodecContext *pngctxp = NULL; /* for screenshot encoder PNG */static void avctx_init_default( AVCodecContext *avctxp ){	if ( NULL == avctxp )		return ;	avctxp->debug_mv = 0;	avctxp->debug = 0;	avctxp->workaround_bugs = 1;	avctxp->skip_frame = AVDISCARD_DEFAULT;	avctxp->skip_idct = AVDISCARD_DEFAULT;	avctxp->skip_loop_filter= AVDISCARD_DEFAULT;	avctxp->error_resilience= FF_ER_CAREFUL;	avctxp->error_concealment= 3;	avctxp->thread_count = 1;	avctxp->idct_algo = FF_IDCT_AUTO;	avctxp->get_buffer = avcodec_default_get_buffer;	avctxp->release_buffer = avcodec_default_release_buffer;}int av_decode_init(void){	AVCodec *codec;	avctx_init_default(dlp_actxp);	avctx_init_default(dlp_vctxp);	av_log(NULL, AV_LOG_INFO, "*************INIT CODEC**************\n");	if ( dlp_vctxp )	{		codec = avcodec_find_decoder(dlp_vctxp->codec_id);		if ( NULL == codec )		{			av_log(NULL, AV_LOG_ERROR, "not found video decoder\n");			dlp_exit(-1);		}		else		{			avcodec_open(dlp_vctxp, codec);			av_log(NULL, AV_LOG_INFO, "Video codec: %s\n", codec->name);		}	}	if ( dlp_actxp )	{		codec = avcodec_find_decoder(dlp_actxp->codec_id);		if ( NULL == codec )		{			av_log(NULL, AV_LOG_ERROR, "not found audio decoder\n");		}		else		{			avcodec_open(dlp_actxp, codec);			av_log(NULL, AV_LOG_INFO, "Audio codec: %s\n", codec->name);		}	}	/*-----------------------------------------------------------------------------	 *  init png encoder for screenshot	 *-----------------------------------------------------------------------------*/	pngctxp = avcodec_alloc_context();	if( avcodec_open( pngctxp, avcodec_find_encoder(CODEC_ID_PNG) ) )	{		av_log(NULL, AV_LOG_ERROR, "PNG encoder for screenshot open error\n");		pngctxp = NULL;	}	else	{		pngctxp->width = dlpctxp->pwidth;		pngctxp->height = dlpctxp->pheight;		pngctxp->pix_fmt = PIX_FMT_RGB24;	}	av_log(NULL, AV_LOG_INFO, "*************INIT CODEC**************\n");	return 0;}int av_decode_uninit(void){	if ( dlp_vctxp )		avcodec_close(dlp_vctxp);	if ( dlp_actxp )		avcodec_close(dlp_actxp);	return 0;}/*----------------------------------------------------------------------------- *  AV output filter *  output_picture --> picture_queue *  output_png     --> file (for screenshot) *-----------------------------------------------------------------------------*/static void output_picture(AVFrame *src_frame, int64_t pts){	int ret;	static struct SwsContext *img_convert_ctx;	int dst_pix_fmt = dlpctxp->pixfmt; /* PIX_FMT_YUV420P */	AVPicture_t *pict;	AVPicture *pic;	pict = av_mallocz(sizeof(AVPicture_t));	pic = (AVPicture*)pict;	ret = avpicture_alloc(pic, dst_pix_fmt, dlpctxp->pwidth, dlpctxp->pheight);	if ( -1 == ret )	{		av_log(NULL, AV_LOG_ERROR, "av picture alloc err\n");		goto fail_p;	}	img_convert_ctx = sws_getCachedContext(img_convert_ctx,	                                       dlpctxp->width, dlpctxp->height,	                                       dlp_vctxp->pix_fmt,	                                       dlpctxp->pwidth, dlpctxp->pheight,	                                       dst_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);	if (img_convert_ctx == NULL)	{		av_log(NULL, AV_LOG_ERROR, "Cannot initialize the conversion context\n");		avpicture_free(pic);		goto fail_p;	}	sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,	          0, dlpctxp->pheight, pic->data, pic->linesize);	av_log(NULL, AV_LOG_DEBUG, "scaled picture: %d,%d,%d,%d\n",	       pic->linesize[0], pic->linesize[1],	       pic->linesize[2], pic->linesize[3]);	pict->pts = pts;	dlp_queue_push_tail(picture_queue, pict);	return;fail_p:	av_free(pict);	return;}static void output_png(AVFrame *frame){	int ret, size, bufsize;	AVPicture *pic;	AVFrame *dst_frame;	static struct SwsContext *img_convert_ctx;	uint8_t *pngbuf;	dst_frame= avcodec_alloc_frame();	if ( NULL == dst_frame )	{		av_log(NULL, AV_LOG_ERROR, "screenshot png: alloc frame faild\n");		return ;	}	pic = (AVPicture*)dst_frame;	ret = avpicture_alloc(pic, pngctxp->pix_fmt, dlpctxp->pwidth, dlpctxp->pheight);	if ( -1 == ret )	{		av_log(NULL, AV_LOG_ERROR, "screenshot png: av picture alloc err\n");		av_free(dst_frame);		return ;	}	bufsize = dlpctxp->pwidth * dlpctxp->pheight * 3 * 2;	pngbuf = av_malloc( bufsize );	img_convert_ctx = sws_getCachedContext(img_convert_ctx,			dlpctxp->width, dlpctxp->height,			dlp_vctxp->pix_fmt,			dlpctxp->pwidth, dlpctxp->pheight,			pngctxp->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);	if (img_convert_ctx == NULL)	{		av_log(NULL, AV_LOG_ERROR, "screenshot png: cannot init the conversion context\n");		avpicture_free(pic);		av_free(dst_frame);		av_free(pngbuf);		return ;	}	sws_scale(img_convert_ctx, frame->data, frame->linesize,			0, dlpctxp->pheight, pic->data, pic->linesize);	size = avcodec_encode_video(pngctxp, pngbuf, bufsize, dst_frame);	if( size > 0 )	{		char pngfile[128];		FILE *fp = fopen(pngfile, "w");		sprintf(pngfile, "screenshot-%ld.png", time(NULL));		if( fp )		{			fwrite( pngbuf, size, 1, fp );			fclose(fp);		}	}	avpicture_free(pic);	av_free(dst_frame);	av_free(pngbuf);}/*----------------------------------------------------------------------------- *  AV decode thread *-----------------------------------------------------------------------------*/static void *video_decode_thread(void *arg){	int got_picture = 0;	AVPacket *pkt;	AVFrame *frame;	frame= avcodec_alloc_frame();	if ( NULL == frame )	{		av_log(NULL, AV_LOG_ERROR, "video thread alloc frame faild\n");		dlp_exit(-1);	}	while (1)	{		while ( dlp_queue_length(picture_queue) > MAX_PICTURE_QUEUE_LEN )		{			usleep(50*1000);			continue;		}		pkt = dlp_queue_pop_head(video_packet_queue);		if ( NULL == pkt )		{			dlp_wait_on_queue(video_packet_queue);			continue;		}		avcodec_decode_video(dlp_vctxp, frame, &got_picture, pkt->data, pkt->size);		if ( got_picture )		{			if( dlpctxp->screenshot && pngctxp )			{				output_png(frame);				dlpctxp->screenshot = 0;			}			output_picture(frame, pkt->pts);		}		/* MUST FREE packet here */		pkt->destruct(pkt);		av_free(pkt);	}	return 0;}static void *audio_decode_thread(void *arg){	AVPacket *pkt;	AVSample *s;	int ret = 0 , frame_size, pktsize;	uint8_t *samples;	uint8_t *pktdata;	samples = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);	while (1)	{		while ( dlp_queue_length(samples_queue) > MAX_SAMPLES_QUEUE_LEN )		{			usleep(50*1000);			continue;		}		pkt = dlp_queue_pop_head(audio_packet_queue);		if ( NULL == pkt )		{			dlp_wait_on_queue(audio_packet_queue);			continue;		}		pktdata = pkt->data;		pktsize = pkt->size;		/* the audio packet can contain several frames */		while ( pkt->size > 0 )		{			frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;			/* return: ret is consumed pkt len,			 * return: frame_size is output samples len */			ret = avcodec_decode_audio2(dlp_actxp,					(int16_t*)samples, &frame_size, pktdata, pktsize);			if ( ret < 0 )			{				/* if error, just output silence */				frame_size = 2048;				memset(samples, 0, 2048);				break;			}			pktsize -= ret;			pktdata += ret;			if ( frame_size <= 0 )			{				goto next_pkt;				/* will be decode continue, contain several frames */				continue;			}			break;		}		s = av_mallocz( sizeof(AVSample) );		av_new_sample( s, frame_size );		memcpy( s->data, samples, frame_size );		/* for sync AV better */		s->pts = pkt->pts;		dlp_queue_push_tail(samples_queue, s);next_pkt:		/* MUST FREE packet here */		pkt->destruct( pkt );		av_free(pkt);	}	return 0;}void create_avdecode_thread(void *arg){	pthread_t threadid;	if ( pthread_create(&threadid, NULL, video_decode_thread, NULL) )	{		av_log(NULL, AV_LOG_INFO, "video decode thread start error\n");		dlp_exit(-1);	}	if ( pthread_create(&threadid, NULL, audio_decode_thread, NULL) )	{		av_log(NULL, AV_LOG_INFO, "audio decode thread start error\n");		dlp_exit(-1);	}	av_log(NULL, AV_LOG_INFO, "video decode thread start\n");	av_log(NULL, AV_LOG_INFO, "audio decode thread start\n");}/*----------------------------------------------------------------------------- *  User Interface functions *-----------------------------------------------------------------------------*/void dlp_screen_shot(void){	dlpctxp->screenshot = 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -