修改cavs_decode_frame函数,使其解出一帧数据后返回
static int cavs_decode_frame(AVCodecContext * avctx,void *data, int *data_size,
const uint8_t * buf, int buf_size) {
AVSContext *h = avctx->priv_data;
MpegEncContext *s = &h->s;
int input_size;
const uint8_t *buf_end;
const uint8_t *buf_ptr;
AVFrame *picture = data;
uint32_t stc = -1;
//add by xugx 20080223
int ok=0;
s->avctx = avctx;
if (buf_size == 0) {
if(!s->low_delay && h->DPB[0].data[0]) {
*data_size = sizeof(AVPicture);
*picture = *(AVFrame *) &h->DPB[0];
}
return 0;
}
buf_ptr = buf;
buf_end = buf + buf_size;
for(;;) {
//add by xugx 20080223
if(ok)
{
//av_log(avctx,AV_LOG_ERROR,"decode one picture success reutrn %d\n",buf_ptr - buf - s->parse_context.last_index);
return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
}
buf_ptr = ff_find_start_code(buf_ptr,buf_end, &stc);
if(stc & 0xFFFFFE00)
return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
input_size = (buf_end - buf_ptr)*8;
switch(stc) {
case CAVS_START_CODE:
init_get_bits(&s->gb, buf_ptr, input_size);
decode_seq_header(h);
break;
case PIC_I_START_CODE:
if(!h->got_keyframe) {
if(h->DPB[0].data[0])
avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]);
if(h->DPB[1].data[0])
avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]);
h->got_keyframe = 1;
}
case PIC_PB_START_CODE:
*data_size = 0;
if(!h->got_keyframe)
break;
init_get_bits(&s->gb, buf_ptr, input_size);
h->stc = stc;
if(decode_pic(h))
break;
*data_size = sizeof(AVPicture);
if(h->pic_type != FF_B_TYPE) {
if(h->DPB[1].data[0]) {
*picture = *(AVFrame *) &h->DPB[1];
} else {
*data_size = 0;
}
} else
*picture = *(AVFrame *) &h->picture;
//add by xugx 20080223
ok=1;
break;
case EXT_START_CODE:
//mpeg_decode_extension(avctx,buf_ptr, input_size);
break;
case USER_START_CODE:
//mpeg_decode_user_data(avctx,buf_ptr, input_size);
break;
default:
if (stc >= SLICE_MIN_START_CODE &&
stc <= SLICE_MAX_START_CODE) {
init_get_bits(&s->gb, buf_ptr, input_size);
decode_slice_header(h, &s->gb);
}
break;
}
}
}
新的main函数,使其解码AVS文件
#define INBUF_SIZE 1024*1024+50000
//#define INBUF_SIZE 1024*512
void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
{
FILE *f;
int i;
f=fopen(filename,"w");
fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
for(i=0;i<ysize;i++)
fwrite(buf + i * wrap,1,xsize,f);
fclose(f);
}
void yuv_save(unsigned char *buf,int wrap,int xsize,int ysize,FILE *f)
{
int i;
for(i=0;i<ysize;i++)
fwrite(buf+i*wrap,1,xsize,f);
}
//void video_decode_example(const char *outfilename, const char *filename)
int main(int argc,char **argv)
{
char* filename=argv[1];
char* outfilename=argv[2];
AVCodec *codec;
AVCodecContext *c= NULL;
int frame, size, got_picture, len;
FILE *f,*fout;
AVFrame *picture;
uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
//uint8_t inbuf[INBUF_SIZE ], *inbuf_ptr;
char buf[1024];
/* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
// memset(inbuf , 0, INBUF_SIZE);
printf("Video decoding\n");
/* must be called before using avcodec lib */
avcodec_init();
/* register all the codecs */
avcodec_register_all();
/* find the mpeg1 video decoder */
codec = avcodec_find_decoder(CODEC_ID_CAVS);
// codec=&cavs_decoder;
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c= avcodec_alloc_context();
picture= avcodec_alloc_frame();
if(codec->capabilities&CODEC_CAP_TRUNCATED)
c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */
/* For some codecs, such as msmpeg4 and mpeg4, width and height
MUST be initialized there because this information is not
available in the bitstream. */
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
/* the codec gives us the frame size, in samples */
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
fout=fopen(outfilename,"wb");
if(!fout)
{
fprintf(stderr,"could not open %s\n",outfilename);
exit(1);
}
frame = 0;
int i=0;
int first=1;
int left=0;
int sum;
for(;;) {
printf("fread %d\n",i++);
//size = fread(inbuf, 1, INBUF_SIZE, f);
size = fread(inbuf+left, 1, INBUF_SIZE-left, f);
printf("size1=%d\n",size);
size+=left;
printf("size2=%d\n",size);
//if (size == 0)
if(size<=left)
break;
/* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
and this is the only method to use them because you cannot
know the compressed data size before analysing it.
BUT some other codecs (msmpeg4, mpeg4) are inherently frame
based, so you must call them with all the data for one
frame exactly. You must also initialize 'width' and
'height' before initializing them. */
/* NOTE2: some codecs allow the raw parameters (frame size,
sample rate) to be changed at any frame. We handle this, so
you should also take care of it */
/* here, we use a stream based decoder (mpeg1video), so we
feed decoder and see if it could decode a frame */
inbuf_ptr = inbuf;
sum=0;
while (size > 0) {
len = avcodec_decode_video(c, picture, &got_picture,
inbuf_ptr, size);
sum+=len;
printf("len=%d sum=%d\n",len,sum);
if (len < 0) {
fprintf(stderr, "Error while decoding frame %d\n", frame);
exit(1);
}
if (got_picture) {
printf("saving frame %3d\n", frame);
fflush(stdout);
first=0;
/* the picture is allocated by the decoder. no need to
free it */
snprintf(buf, sizeof(buf), outfilename, frame);
// pgm_save(picture->data[0], picture->linesize[0],
// c->width, c->height, buf);
// printf("linsize0=%d linesize1=%d linesize2=%d\n",picture->linesize[0],picture->linesize[1],picture->linesize[2]);
//printf("width=%d height=%d\n",c->width,c->height);
yuv_save(picture->data[0],picture->linesize[0],c->width,c->height,fout);
yuv_save(picture->data[1],picture->linesize[1],c->width/2,c->height/2,fout);
yuv_save(picture->data[2],picture->linesize[2],c->width/2,c->height/2,fout);
frame++;
}
/*else*/
/*{*/
/*if(!first)*/
/*{*/
/*memcpy(inbuf,inbuf_ptr,size);*/
/*left=size;*/
/*break;*/
/*}*/
/*}*/
size -= len;
inbuf_ptr += len;
if(size<60000)
{
memcpy(inbuf,inbuf_ptr,size);
left=size;
break;
}
}
}
//the last buffer content
inbuf_ptr = inbuf;
sum=0;
while (size > 0) {
len = avcodec_decode_video(c, picture, &got_picture,
inbuf_ptr, size);
sum+=len;
printf("len=%d sum=%d\n",len,sum);
if (len < 0) {
fprintf(stderr, "Error while decoding frame %d\n", frame);
exit(1);
}
if (got_picture) {
printf("saving frame %3d\n", frame);
fflush(stdout);
first=0;
/* the picture is allocated by the decoder. no need to
free it */
snprintf(buf, sizeof(buf), outfilename, frame);
// pgm_save(picture->data[0], picture->linesize[0],
// c->width, c->height, buf);
// printf("linsize0=%d linesize1=%d linesize2=%d\n",picture->linesize[0],picture->linesize[1],picture->linesize[2]);
//printf("width=%d height=%d\n",c->width,c->height);
yuv_save(picture->data[0],picture->linesize[0],c->width,c->height,fout);
yuv_save(picture->data[1],picture->linesize[1],c->width/2,c->height/2,fout);
yuv_save(picture->data[2],picture->linesize[2],c->width/2,c->height/2,fout);
frame++;
}
size -= len;
inbuf_ptr += len;
}
/* some codecs, such as MPEG, transmit the I and P frame with a
latency of one frame. You must do the following to have a
/* chance to get the last frame of the video */
/*len = avcodec_decode_video(c, picture, &got_picture,*/
/*NULL, 0);*/
/*if (got_picture) {*/
/*printf("saving last frame %3d\n", frame);*/
/*fflush(stdout);*/
/* *//* the picture is allocated by the decoder. no need to*/
/* free it */
/*snprintf(buf, sizeof(buf), outfilename, frame);*/
/*pgm_save(picture->data[0], picture->linesize[0],*/
/*c->width, c->height, buf);*/
/*frame++;*/
/*}*/
fclose(f);
fclose(fout);
avcodec_close(c);
av_free(c);
av_free(picture);
printf("\n");
return 0;
}
没有评论:
发表评论