JD2022-TU1/main/extern/Camcam/LIBS/ENCDEC/AVCodec/AVCodec.cpp

452 lines
11 KiB
C++

#include "SCENE.h"
#ifdef VIDEO_OPENLIB
#pragma comment(lib, "..\\LIBS\\ENCDEC\\avcodec-51.lib")
#pragma comment(lib, "..\\LIBS\\ENCDEC\\avdevice-52.lib")
#pragma comment(lib, "..\\LIBS\\ENCDEC\\avformat-52.lib")
#pragma comment(lib, "..\\LIBS\\ENCDEC\\avutil-49.lib")
extern WORLD *TheScene;
extern "C" {
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
}
//#define COPY_CASH
#define MAX_DELAY_TIME 60
#define V_ENCDEC_CODEC CODEC_ID_MPEG4 //CODEC_ID_H263 CODEC_ID_FLV1
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_PIX_FMT PIX_FMT_YUV420P
#define PICTURE_PIX_FMT PIX_FMT_RGB32
#define A_ENCDEC_CODEC CODEC_ID_MP3 //CODEC_ID_MP2 //
static AVCodec *vCodecEnc = NULL;
static AVCodec *vCodecDec = NULL;
static AVCodec *aCodecEnc = NULL;
static AVCodec *aCodecDec = NULL;
typedef struct _VideoData
{
AVCodecContext *c;
AVFrame *pict;
AVFrame *noBufferPict;
} VideoData;
typedef struct _AudioData
{
AVCodecContext *c;
int head;
int sampleSize;
uint8_t *inBuffer;
} AudioData;
typedef struct _AVData
{
VideoData *vd;
AudioData *sd;
} AVData;
int AVCodec_Init()
{
av_register_all();
if (!vCodecEnc)
vCodecEnc = avcodec_find_encoder(V_ENCDEC_CODEC);
if (!vCodecDec)
vCodecDec = avcodec_find_decoder(V_ENCDEC_CODEC);
if (!aCodecEnc)
aCodecEnc = avcodec_find_encoder(A_ENCDEC_CODEC);
if (!aCodecDec)
aCodecDec = avcodec_find_decoder(A_ENCDEC_CODEC);
return vCodecEnc && vCodecDec && aCodecEnc && aCodecDec;
}
void *AVCodec_INIT(MAP *PPicture, bool encode)
{
AVData *data = (AVData *)CC_malloc(sizeof(VideoData));
VideoData *vd;
AudioData *sd;
AVCodec *codec;
if (encode)
codec = vCodecEnc;
else
codec = vCodecDec;
vd = data->vd = (VideoData *)CC_malloc(sizeof(VideoData));
memset(vd, 0, sizeof(VideoData));
vd->c = (AVCodecContext *) avcodec_alloc_context();
vd->c->codec_type = CODEC_TYPE_VIDEO;
vd->c->codec_id = vCodecDec->id;
/* put sample parameters */
vd->c->bit_rate = 10000;
vd->c->me_method = 1;
/* 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->gop_size = 256; /* emit one intra frame every 256 frames at most */
vd->c->pix_fmt = STREAM_PIX_FMT;
/* Special case */
if (vd->c->codec_id == CODEC_ID_MPEG2VIDEO)
vd->c->max_b_frames = 2;
if (vd->c->codec_id == CODEC_ID_MPEG1VIDEO)
vd->c->mb_decision = 2;
if (avcodec_open(vd->c, codec) < 0)
return NULL;
int size;
uint8_t *picture_buf;
vd->pict = avcodec_alloc_frame();
vd->noBufferPict= avcodec_alloc_frame();
if (!vd->pict || !vd->noBufferPict)
return NULL;
size = avpicture_get_size(STREAM_PIX_FMT, PPicture->SX, PPicture->SY);
picture_buf = (uint8_t *)av_malloc(size);
if (!picture_buf)
{
av_free(vd->pict);
av_free(vd->noBufferPict);
return NULL;
}
avpicture_fill((AVPicture *)vd->pict, picture_buf, STREAM_PIX_FMT, PPicture->SX, PPicture->SY);
if (encode)
codec = aCodecEnc;
else
codec = aCodecDec;
sd = data->sd = (AudioData *)CC_malloc(sizeof(AudioData));
memset(sd, 0, sizeof(AudioData));
sd->c = (AVCodecContext *) avcodec_alloc_context();
sd->c->codec_id = codec->id;
sd->c->codec_type = CODEC_TYPE_AUDIO;
sd->c->bit_rate = SND_BIT_RATE;
sd->c->sample_rate = SND_SAMPLES;
sd->c->channels = SND_NB_CHANNELS;
if (avcodec_open(sd->c, codec) < 0)
return NULL;
if (encode)
{
sd->sampleSize = sd->c->frame_size*2*sd->c->channels;
sd->inBuffer = (uint8_t *)CC_malloc(data->sd->sampleSize);
sd->head = MicroInAddHead(&TheScene->microIn);
} else
{
sd->sampleSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
sd->inBuffer = (uint8_t *)CC_malloc(data->sd->sampleSize);
}
MicroOutInit(&TheScene->microOut);
return data;
}
void AVCodec_CLOSE(void *H)
{
if (H)
{
AVData *data = (AVData *)H;
av_free(data->vd->c);
av_free(data->vd->pict);
av_free(data->vd->noBufferPict);
CC_free(data->vd);
MicroInDelHead(&TheScene->microIn, data->sd->head, 1);
av_free(data->sd->c);
CC_free(data->sd->inBuffer);
CC_free(data->sd);
CC_free(data);
}
}
void *AVCodec_Encode_INIT(MAP *PPicture)
{
if (!AVCodec_Init())
return NULL;
return AVCodec_INIT(PPicture, true);
}
u32 AVCodec_Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH)
{
int encodedSize;
AVData *data = (AVData *)H;
if (!H) return 0;
avpicture_fill((AVPicture *)data->vd->noBufferPict, (uint8_t *)PPicture->GetBase(), PICTURE_PIX_FMT, PPicture->SX, PPicture->SY);
encodedSize = img_convert( (AVPicture *)data->vd->pict, STREAM_PIX_FMT,
(AVPicture *)data->vd->noBufferPict, PICTURE_PIX_FMT, PPicture->SX, PPicture->SY);
if (FROMSCRATCH)
{
data->vd->pict->pict_type = FF_I_TYPE;
data->vd->pict->key_frame = 1;
//data->vd->pict->key_frame = 1;
} else
{
data->vd->pict->pict_type = FF_P_TYPE;
data->vd->pict->key_frame = 0;
}
encodedSize = avcodec_encode_video(data->vd->c, (uint8_t *)Buffer, DATA_MAX, data->vd->pict);
return encodedSize;
}
u32 AVCodec_Encode_AUDIO(void *H, char *Buffer)
{
AVData *data = (AVData *)H;
int encodedSize = 0;
char *BufferPtr = Buffer;
int bufferSize = DATA_MAX_SOUND;
if (!H) return 0;
#ifdef COPY_CASH
encodedSize = MicroInReadMax(&TheScene->microIn, data->sd->head,
(char *)Buffer , DATA_MAX_SOUND);
bufferSize -= encodedSize;
#else
while ( bufferSize > 0 &&
MicroInReadExactly( &TheScene->microIn, data->sd->head,
(char *)data->sd->inBuffer,data->sd->sampleSize))
{
//MicroOutWrite(&TheScene->microOut, (char *)data->sd->inBuffer, data->sd->sampleSize);
int encSize = avcodec_encode_audio(data->sd->c, (uint8_t *)BufferPtr, bufferSize, (short *) data->sd->inBuffer);
encodedSize += encSize;
BufferPtr += encSize;
bufferSize -= encSize;
}
#endif
if (bufferSize <= 0 || MicroInGetBufferedTime(&TheScene->microIn, data->sd->head) > MAX_DELAY_TIME)
MicroInFlush(&TheScene->microIn, data->sd->head);
return encodedSize;
}
void AVCodec_Encode_CLOSE(void *H)
{
AVCodec_CLOSE(H);
}
void *AVCodec_Decode_INIT(MAP *PPicture)
{
if (!AVCodec_Init())
return NULL;
return AVCodec_INIT(PPicture, false);
}
u32 AVCodec_Decode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 BufferSize)
{
int got_picture = 0;
int encodedSize;
AVData *data = (AVData *)H;
if (!data || !BufferSize)
return 0;
encodedSize = avcodec_decode_video(data->vd->c, data->vd->pict, &got_picture, (uint8_t *)Buffer, BufferSize);
if (!got_picture || encodedSize <= 0)
return 0;
avpicture_fill((AVPicture *)data->vd->noBufferPict, (uint8_t *)PPicture->GetBase(), PICTURE_PIX_FMT, PPicture->SX, PPicture->SY);
encodedSize = img_convert( (AVPicture *)data->vd->noBufferPict, PICTURE_PIX_FMT,
(AVPicture *)data->vd->pict, STREAM_PIX_FMT, PPicture->SX, PPicture->SY);
return encodedSize;
}
u32 AVCodec_Decode_AUDIO(void *H, char *Buffer, int size)
{
AVData *data = (AVData *)H;
int encodedSize = 0;
int encodedFrameSize = 0;
char *BufferPtr = Buffer;
if (!H) return 0;
// FROMSCRATCH NOT IMPLEMENTED YET !!
//if (MicroOutGetBufferedTime(&TheScene->microOut) > MAX_DELAY_TIME)
// MicroOutFlush(&TheScene->microOut);
#ifdef COPY_CASH
MicroOutWrite(&TheScene->microOut, Buffer, size);
#else
while (size > 0)
{
encodedSize = data->sd->sampleSize;
encodedFrameSize= avcodec_decode_audio2(data->sd->c, (int16_t *)data->sd->inBuffer,
&encodedSize, (uint8_t *)Buffer, size);
if (encodedFrameSize > 0)
{
Buffer += encodedFrameSize;
size -= encodedFrameSize;
MicroOutWrite(&TheScene->microOut, (char *)data->sd->inBuffer, encodedSize);
}
else
size = 0;
}
#endif
return encodedSize;
}
void AVCodec_Decode_CLOSE(void *H)
{
AVCodec_CLOSE(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);
}
//*************************************************
//*************************************************
u32 Timer = 0;
typedef struct Multiplexer_
{
u32 Identityfier;
u32 SoundSize;
u32 VideoSize;
u32 UserSize;
} Multiplexer;
#define ENCODE_SOUND
u32 Encode_FRAME_AND_SOUND(void *H, MAP *PPicture, char *DataBuffer, u32 FROMSCRATCH, u32 Q, u32 R)
{
#ifdef ENCODE_SOUND
static u32 LastTime = 0;
Multiplexer *pHeader;
pHeader = (Multiplexer *)DataBuffer;
pHeader ->Identityfier = 'SOUN';
DataBuffer += sizeof(Multiplexer);//*/
/* Encode Video ********************************************************************/
pHeader->VideoSize = Encode_FRAME(H, PPicture, DataBuffer, FROMSCRATCH, Q, R);
DataBuffer += pHeader->VideoSize;
/* Encode Sound ********************************************************************/
pHeader->SoundSize = AVCodec_Encode_AUDIO(H, DataBuffer);
return sizeof(Multiplexer) + pHeader->SoundSize + pHeader->VideoSize;
#else
return Encode_FRAME(H, PPicture, DataBuffer, FROMSCRATCH, Q, R) ;
#endif
}
u32 Decode_FRAME_AND_SOUND(void *H, MAP *PPicture, char *DataBuffer, u32 FROMSCRATCH)
{
#ifdef ENCODE_SOUND
Multiplexer *pHeader;
pHeader = (Multiplexer *)DataBuffer;
DataBuffer += sizeof(Multiplexer);//*/
if (pHeader ->Identityfier == 'SOUN')
{
u32 OKValue;
/* Decode Video ********************************************************************/
OKValue = Decode_FRAME(H, PPicture, DataBuffer, pHeader->VideoSize) ;
DataBuffer += pHeader->VideoSize;//*/
/* Decode Video ********************************************************************/
if (pHeader->SoundSize) AVCodec_Decode_AUDIO(H, DataBuffer, pHeader->SoundSize);
return OKValue;
}
else return -1;
#else
return Decode_FRAME(H, PPicture, DataBuffer, FROMSCRATCH) ;//*/
#endif
}
#else
void * Encode_INIT(MAP *)
{
return NULL;
}
u32 Encode_FRAME(void *, MAP *, char *, u32, u32 Q, u32 R)
{
return 0;
}
void Encode_CLOSE(void *)
{
}
void * Decode_INIT(MAP *)
{
return NULL;
}
u32 Decode_FRAME(void *, MAP *, char *, u32)
{
return 0;
}
void Decode_CLOSE(void *)
{
}
#endif