📄 corepng.c
字号:
/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "avcodec.h"#include "common.h"#include "dsputil.h"#define PNGFrameType_RGB24 0x01#define PNGFrameType_YUY2 0x02#define PNGFrameType_YV12 0x03typedef struct CorePNGCodecPrivate { int16_t wSize; int8_t bType;} CorePNGCodecPrivate;typedef struct CorePNGcontext{ AVCodecContext *avctx; DSPContext dsp; AVFrame picture,prev_picture; CorePNGCodecPrivate private; uint8_t *buf;int buf_size; int shiftX,shiftY; AVCodecContext *decctx; AVFrame decframe;} CorePNGcontext;static int read_image(CorePNGcontext * const a, uint8_t *ptr, int linesize,int flip){ int got_picture=0,ret; a->decframe.data[0]=ptr; a->decframe.linesize[0]=linesize*(flip?-1:1); ret=avcodec_decode_video(a->decctx,&a->decframe,&got_picture,a->buf,a->buf_size); if(ret>0){ a->buf+=ret; a->buf_size-=ret; } return 0;}static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){ CorePNGcontext * const a = avctx->priv_data; int Bpp,num_planes,swapUV=0; AVFrame temp,*p; if (!a->decctx) { a->decctx=avcodec_alloc_context(); avcodec_open(a->decctx,&png_decoder); avcodec_get_frame_defaults(&a->decframe); } temp= a->picture; a->picture= a->prev_picture; a->prev_picture= temp; p= &a->picture; avctx->coded_frame= p; avctx->flags |= CODEC_FLAG_EMU_EDGE; // alternatively we would have to use our own buffer management if(p->data[0]) avctx->release_buffer(avctx, p); p->reference= 1; if(avctx->get_buffer(avctx, p) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } /* special case for last picture */ if (buf_size == 0) { return 0; } a->buf=buf;a->buf_size=buf_size; switch(a->private.bType){ case PNGFrameType_RGB24: read_image(a,a->picture.data[0],a->picture.linesize[0],0); Bpp=3;num_planes=1; break; case PNGFrameType_YUY2: swapUV=1; case PNGFrameType_YV12: read_image(a,a->picture.data[0],a->picture.linesize[0],1); read_image(a,a->picture.data[swapUV?1:2],a->picture.linesize[swapUV?1:2],1); read_image(a,a->picture.data[swapUV?2:1],a->picture.linesize[swapUV?2:1],1); Bpp=1;num_planes=3; break; default: return 0; } if(avctx->sample_fmt==SAMPLE_I){ //indicates that this is a keyframe, CorePNG doesn't store this info in the stream ifself a->picture.key_frame=1; a->picture.pict_type=FF_I_TYPE; }else{ int i,shiftX=0,shiftY=0; a->picture.key_frame=0; a->picture.pict_type=FF_P_TYPE; for(i=0;i<num_planes;i++,shiftX=a->shiftX,shiftY=a->shiftY){ uint8_t *cur=a->picture.data[i],*prev=a->prev_picture.data[i]; int y; for(y=0;y<avctx->height>>shiftY;y++,cur+=a->picture.linesize[i],prev+=a->prev_picture.linesize[i]) a->dsp.add_bytes(cur,prev,avctx->width*Bpp>>shiftX); } } *data_size = sizeof(AVFrame); *(AVFrame*)data = a->picture; return buf_size;}static int decode_init(AVCodecContext *avctx){ CorePNGcontext * const a = avctx->priv_data; dsputil_init(&a->dsp, avctx); a->avctx= avctx; a->picture.data[0]=a->prev_picture.data[0]=NULL; if(avctx->extradata_size == sizeof(CorePNGCodecPrivate)) memcpy(&a->private,avctx->extradata,sizeof(CorePNGCodecPrivate)); else{ a->private.wSize = sizeof(CorePNGCodecPrivate); a->private.bType = PNGFrameType_RGB24; } switch(a->private.bType){ case PNGFrameType_RGB24: avctx->pix_fmt = PIX_FMT_BGR24; break; case PNGFrameType_YUY2: avctx->pix_fmt = PIX_FMT_YUV422P; break; case PNGFrameType_YV12: avctx->pix_fmt = PIX_FMT_YUV420P; break; } avctx->has_b_frames=0; avcodec_get_chroma_sub_sample(avctx->pix_fmt, &a->shiftX, &a->shiftY); a->decctx=NULL; return 0;}static int decode_done(AVCodecContext *avctx){ CorePNGcontext * const a = avctx->priv_data; if(a->decctx){ avcodec_close(a->decctx); av_free(a->decctx); } return 0;} AVCodec corepng_decoder = { "corepng", CODEC_TYPE_VIDEO, CODEC_ID_COREPNG, sizeof(CorePNGcontext), decode_init, NULL, decode_done, decode_frame, 0};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -