123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #include "video_decoder.h"
- #include "../video_common/ffmpeg_api_adapter.h"
- #include "base/video_coding_log.h"
- typedef struct _VideoDecoder{
- AVFrame *dec_picture;
- AVPacket dec_avpkt;
- AVCodecContext *dec_ctx;
- AVCodec *dec;
- struct SwsContext *dec_sws_context;
- DecoderConfig config_;
- }VideoDecoder;
- static AVFrame *alloc_picture(int pix_fmt, int width, int height)
- {
- AVFrame *picture;
- uint8_t *picture_buf;
- int size;
- picture = (AVFrame *)avcodec_alloc_frame();
- if (!picture)
- return NULL;
- size = avpicture_get_size(pix_fmt, width, height);
- picture_buf = (uint8_t *)av_malloc(size);
- if (!picture_buf) {
- av_free(picture);
- return NULL;
- }
- avpicture_fill((AVPicture *)picture, picture_buf,
- pix_fmt, width, height);
- picture->width = width;
- picture->height = height;
- picture->format = pix_fmt;
- return picture;
- }
- static void free_picture(AVFrame *picture)
- {
- av_free(picture->data[0]);
- avcodec_free_frame(&picture);
- }
- static void ffmpeg_yuvframe_copy_to_local_frame(const AVFrame *picture, video_frame *vframe)
- {
- int i =0, j =0, k =0;
- vframe->linesize[0] = picture->width;
- vframe->linesize[1] = picture->width/2;
- vframe->linesize[2] = picture->width/2;
- for(i = 0; i < vframe->height; i++)
- {
- memcpy(vframe->data[0]+vframe->linesize[0]*i,
- picture->data[0]+picture->linesize[0]*i,
- picture->width);
-
- }
- for(j = 0; j < vframe->height/2; j++)
- {
- memcpy(vframe->data[1]+vframe->linesize[1]*j,
- picture->data[1]+picture->linesize[1]*j,
- picture->width/2);
- }
- for(k =0; k < vframe->height/2; k++)
- {
- memcpy(vframe->data[2]+vframe->linesize[2]*k,
- picture->data[2]+picture->linesize[2]*k,
- picture->width/2);
- }
- }
- VideoDecoder *video_decoder_open(const DecoderConfig *config, VideoCodingLogCallBack *log_func){
- int rc;
- VideoDecoder *obj;
-
- video_decode_setup_log(log_func);
- obj = (VideoDecoder *)malloc(sizeof(VideoDecoder));
- memset(obj, 0, sizeof(VideoDecoder));
- memcpy(&obj->config_, config, sizeof(DecoderConfig));
- obj->dec_picture = avcodec_alloc_frame();
- if (!obj->dec_picture) {
- video_decoder_close(obj);
- return NULL;
- }
- obj->dec = avcodec_find_decoder(obj->config_.decode_id);
- if (!obj->dec){
- video_decoder_close(obj);
- return NULL;
- }
- obj->dec_ctx = avcodec_alloc_context3(obj->dec);
- if (!obj->dec_ctx){
- video_decoder_close(obj);
- return NULL;
- }
- obj->dec_ctx->flags |= CODEC_FLAG_LOW_DELAY;
- rc = avcodec_open2(obj->dec_ctx, obj->dec, NULL);
- if (rc != 0){
- video_decoder_close(obj);
- return NULL;
- }
- video_decode_debug(VIDEO_CODING_DEBUG_ENABLE, "video_decoder_open width: %d height: %d decode_id: %d.",
- config->width, config->height, obj->config_.decode_id);
-
- return obj;
- }
- video_frame *video_decoder_process(VideoDecoder *obj, unsigned char *input_packet,
- int length, int *remain_length, int *key_frame){
- int ret = -1;
- int got_picture = -1;
- int len = 0;
- if (!obj){
- return NULL;
- }
- av_init_packet(&obj->dec_avpkt);
- obj->dec_avpkt.data = input_packet;
- obj->dec_avpkt.size = length;
- video_decode_debug(VIDEO_CODING_DEBUG_DECODER, "video_decoder_process length: %d.", length);
- len = avcodec_decode_video2(obj->dec_ctx, obj->dec_picture, &got_picture, &obj->dec_avpkt);
- if (0 > len){
- return NULL;
- }
- if (got_picture) {
- video_frame *frm = video_frame_new(obj->config_.width, obj->config_.height, obj->config_.color_space);
- #if 1
- unsigned char *data[4]={0};
- int linesize[4]={0};
- //miror
- data[0] = obj->dec_picture->data[0];
- data[1] = obj->dec_picture->data[1];
- data[2] = obj->dec_picture->data[2];
- data[3] = obj->dec_picture->data[3];
- linesize[0] = obj->dec_picture->linesize[0];
- linesize[1] = obj->dec_picture->linesize[1];
- linesize[2] = obj->dec_picture->linesize[2];
- linesize[3] = obj->dec_picture->linesize[3];
- data[0] += (obj->dec_picture->height - 1) * linesize[0];
- data[1] += (obj->dec_picture->height/2 - 1) * linesize[1];
- data[2] += (obj->dec_picture->height/2 - 1) * linesize[2];
- linesize[0] = -linesize[0];
- linesize[1] = -linesize[1];
- linesize[2] = -linesize[2];
- //format convert
- obj->dec_sws_context = sws_getCachedContext(obj->dec_sws_context,
- obj->dec_picture->width,
- obj->dec_picture->height,
- obj->dec_picture->format,
- obj->config_.width,
- obj->config_.height,
- (obj->config_.color_space != VIDEO_FORMAT_I420 ? PIX_FMT_BGR24 : PIX_FMT_YUV420P),
- SWS_FAST_BILINEAR,
- NULL,
- NULL,
- NULL);
- sws_scale(obj->dec_sws_context,
- data,
- linesize,
- 0,
- obj->dec_picture->height,
- frm->data,
- frm->linesize);
- #else
- if((obj->config_.width != obj->dec_picture->width) ||
- (obj->config_.height != obj->dec_picture->height) ||
- (obj->config_.color_space != obj->dec_picture->format)){
- obj->dec_sws_context = sws_getCachedContext(obj->dec_sws_context,
- obj->dec_picture->width,
- obj->dec_picture->height,
- obj->dec_picture->format,
- obj->config_.width,
- obj->config_.height,
- (obj->config_.color_space != VIDEO_FORMAT_I420 ? PIX_FMT_BGR24 : PIX_FMT_YUV420P),
- SWS_FAST_BILINEAR,
- NULL,
- NULL,
- NULL);
- sws_scale(obj->dec_sws_context,
- obj->dec_picture->data,
- obj->dec_picture->linesize,
- 0,
- obj->dec_picture->height,
- frm->data,
- frm->linesize);
- } else {
- if (obj->config_.color_space == VIDEO_FORMAT_I420){
- ffmpeg_yuvframe_copy_to_local_frame(obj->dec_picture, frm);
- } else {
- memcpy(frm->data[0], obj->dec_picture->data[0], obj->dec_picture->width*obj->dec_picture->height*3);
- frm->linesize[0] = obj->dec_picture->linesize[0];
- }
- }
- #endif
- *key_frame = obj->dec_picture->key_frame;
- frm->width = obj->config_.width;
- frm->height = obj->config_.height;
- frm->format = obj->config_.color_space;
-
- *remain_length -= len;
- return frm;
- }
- *remain_length -= len;
- return NULL;
- }
- void video_decoder_close(VideoDecoder *obj){
- if (obj != NULL) {
- if (obj->dec_picture != NULL) {
- avcodec_free_frame(&obj->dec_picture);
- obj->dec_picture = NULL;
- }
- if (obj->dec_ctx != NULL) {
- avcodec_close(obj->dec_ctx);
- av_free(obj->dec_ctx);
- obj->dec_ctx = NULL;
- }
-
- free((void *)obj);
- video_decode_debug(VIDEO_CODING_DEBUG_DECODER, "video_decoder_close.");
- }
- video_decode_unsetup_log();
- }
|