📄 avdecode.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 + -