#ifdef _OPENLIB #include "SCENE.h" extern "C" { #include "avformat.h" #include "avcodec.h" #include "avutil.h" } #define STREAM_FRAME_RATE 25 /* 25 images/s */ #define STREAM_PIX_FMT PIX_FMT_YUV420P //PIX_FMT_YUV420P /* default pix_fmt *///PIX_FMT_YUV420P //PIX_FMT_RGB24 // #define PICTURE_PIX_FMT PIX_FMT_RGB32 static AVCodec *codecEnc = NULL; static AVCodec *codecDec = NULL; typedef struct _VideoData { AVCodecContext *c; AVFrame *pict; SwsContext } VideoData; void AVCodec_Init() { av_register_all(); if (!codecEnc) codecEnc= avcodec_find_encoder(CODEC_ID_FLV1); if (!codecDec) codecDec= avcodec_find_decoder(CODEC_ID_FLV1); //CODEC_ID_H263 } //void *Encode_INIT(MAP *PPicture) //u32 Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH) //void Encode_CLOSE(void *H) /* if (!fmt) fmt = guess_format("mpeg", NULL, NULL); AVCodec *codec= avcodec_find_encoder(s->avctx->codec_id); AVCodecContext *c= avcodec_alloc_context(); AVFrame input[FF_MAX_B_FRAMES+2]; const int scale= s->avctx->brd_scale; int i, j, out_size; int outbuf_size= s->width * s->height; //FIXME uint8_t *outbuf= av_malloc(outbuf_size); ImgReSampleContext *resample; int64_t best_rd= INT64_MAX; int best_b_count= -1; const int lambda2= s->lambda2; c->width = s->width >> scale; c->height= s->height>> scale; c->flags= CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR | CODEC_FLAG_INPUT_PRESERVED; c->flags|= s->avctx->flags & CODEC_FLAG_QPEL; c->mb_decision= s->avctx->mb_decision; c->me_cmp= s->avctx->me_cmp; c->mb_cmp= s->avctx->mb_cmp; c->me_sub_cmp= s->avctx->me_sub_cmp; c->pix_fmt = PIX_FMT_YUV420P; c->time_base= s->avctx->time_base; c->max_b_frames= s->max_b_frames; */ void *AVCodec_Encode_INIT(MAP *PPicture) { AVCodec_Init(); VideoData *vd = (VideoData *)CC_malloc(sizeof(VideoData)); vd->c = (AVCodecContext *) avcodec_alloc_context(); vd->c->codec_id = codecEnc->id; vd->c->codec_type = CODEC_TYPE_VIDEO; /* put sample parameters */ vd->c->bit_rate = 400000; /* resolution must be a multiple of two */ vd->c->width = PPicture->SX; vd->c->height = PPicture->SY; /* time base: this is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ vd->c->time_base.den = STREAM_FRAME_RATE; vd->c->time_base.num = 1; //vd->c->gosize = 12; /* emit one intra frame every twelve frames at most */ vd->c->pix_fmt = STREAM_PIX_FMT; if (vd->c->codec_id == CODEC_ID_MPEG2VIDEO) { /* just for testing, we also add B frames */ vd->c->max_b_frames = 2; } if (vd->c->codec_id == CODEC_ID_MPEG1VIDEO){ /* Needed to avoid using macroblocks in which some coeffs overflow. This does not happen with normal video, it just happens here as the motion of the chroma plane does not match the luma plane. */ vd->c->mb_decision = 2; } /* some formats want stream headers to be separate */ // vd->c->flags |= CODEC_FLAG_GLOBAL_HEADER; if (avcodec_open(vd->c, codecEnc) < 0) { CC_free(vd->c); CC_free(vd); return NULL; } int size; uint8_t *picture_buf; vd->pict = avcodec_alloc_frame(); if (!vd->pict) return NULL; size = avpicture_get_size(PICTURE_PIX_FMT, PPicture->SX, PPicture->SY); picture_buf = av_malloc(size); if (!picture_buf) { CC_free(vd->pict); return NULL; } avpicture_fill((AVPicture *)vd->pict, picture_buf, PICTURE_PIX_FMT, PPicture->SX, PPicture->SY); return vd; } u32 AVCodec_Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH) { int encodedSize; VideoData *vd = (VideoData *)H; if (!H) return 0; encodedSize = avcodec_encode_video(vd->c, (uint8_t *)Buffer + 4, DATA_MAX-4, vd->pict); *((int *)Buffer) = encodedSize; return encodedSize; } void AVCodec_Encode_CLOSE(void *H) { if (H) av_free(H); } void *AVCodec_Decode_INIT(MAP *PPicture) { AVCodec_Init(); AVCodecContext *c = (AVCodecContext *) avcodec_alloc_context(); c->codec_id = codecDec->id; c->codec_type = CODEC_TYPE_VIDEO; /* put sample parameters */ c->bit_rate = 400000; /* resolution must be a multiple of two */ c->width = PPicture->SX; c->height = PPicture->SY; /* time base: this is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ c->time_base.den = STREAM_FRAME_RATE; c->time_base.num = 1; //c->gosize = 12; /* emit one intra frame every twelve frames at most */ c->pix_fmt = STREAM_PIX_FMT; if (c->codec_id == CODEC_ID_MPEG2VIDEO) { /* just for testing, we also add B frames */ c->max_b_frames = 2; } if (c->codec_id == CODEC_ID_MPEG1VIDEO){ /* Needed to avoid using macroblocks in which some coeffs overflow. This does not happen with normal video, it just happens here as the motion of the chroma plane does not match the luma plane. */ c->mb_decision = 2; } // some formats want stream headers to be separate // c->flags |= CODEC_FLAG_GLOBAL_HEADER; return c; } u32 AVCodec_Decode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH) { AVFrame pict; int got_picture_ptr = FROMSCRATCH; int encodedSize = *((int *)Buffer); if (encodedSize > 0) { avpicture_fill((AVPicture *)&pict, (uint8_t *)PPicture->BASE, PICTURE_PIX_FMT, PPicture->SX, PPicture->SY); return avcodec_decode_video((AVCodecContext *)H, &pict, &got_picture_ptr, (uint8_t *)Buffer+4, encodedSize); } else return 0; } void AVCodec_Decode_CLOSE(void *H) { if (H) av_free(H); } void *Encode_INIT(MAP *PPicture) { return AVCodec_Encode_INIT(PPicture); } u32 Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH, u32 Q, u32 R) { return AVCodec_Encode_FRAME(H, PPicture, Buffer, FROMSCRATCH); } void Encode_CLOSE(void *H) { AVCodec_Encode_CLOSE(H); } void *Decode_INIT(MAP *PPicture) { return AVCodec_Decode_INIT(PPicture); } u32 Decode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH) { return AVCodec_Decode_FRAME(H, PPicture, Buffer, FROMSCRATCH); } void Decode_CLOSE(void *H) { AVCodec_Decode_CLOSE(H); } #endif