2008年2月25日星期一

cavs -20080225

修改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;
}

没有评论: