corepng.c
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C语言 代码 · 共 190 行
C
190 行
/*
* 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 "allcodecs.h"
#include "common.h"
#include "dsputil.h"
#define PNGFrameType_RGB24 0x01
#define PNGFrameType_YUY2 0x02
#define PNGFrameType_YV12 0x03
typedef 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 + =
减小字号Ctrl + -
显示快捷键?