Mercurial > mplayer.hg
diff libmpcodecs/vd_ffmpeg.c @ 13190:8be7dbcea0be
AVC (fourcc avc1) in mp4 support
author | rtognimp |
---|---|
date | Sun, 29 Aug 2004 13:52:19 +0000 |
parents | 2af30a65a772 |
children | a83623b3b86a |
line wrap: on
line diff
--- a/libmpcodecs/vd_ffmpeg.c Sat Aug 28 21:01:15 2004 +0000 +++ b/libmpcodecs/vd_ffmpeg.c Sun Aug 29 13:52:19 2004 +0000 @@ -72,6 +72,11 @@ double inv_qp_sum; int ip_count; int b_count; + // AVC data + int got_avcC; + int nal_length_size; + void *data_bak; + int len_bak; } vd_ffmpeg_ctx; //#ifdef FF_POSTPROCESS @@ -339,6 +344,10 @@ memcpy(avctx->extradata, ((int*)sh->ImageDesc)+1, avctx->extradata_size); } + if(sh->format == mmioFOURCC('a', 'v', 'c', '1')) { + ctx->got_avcC = 0; + } + if(sh->bih) avctx->bits_per_sample= sh->bih->biBitCount; @@ -678,6 +687,36 @@ uint32_t chunktab; // offset to chunk offset array } dp_hdr_t; + +/** + * Add sync to a nal and queue it in buffer, increasing buffer size as needed + * @param dest pointer to current buffer area + * @param destsize pointer to size of current dest area + * @param source pointer to source nal data (after length bytes) + * @param nal_len length of nal data + */ +unsigned char* avc1_addnal(unsigned char *dest, int *destsize, unsigned char* source, int nal_len) +{ + unsigned char *temp; + int tempsize; + + tempsize = *destsize + nal_len + 4; + temp = malloc (tempsize); + if (dest) + memcpy (temp, dest, *destsize); + temp[*destsize] = 0; + temp[*destsize+1] = 0; + temp[*destsize+2] = 0; + temp[*destsize+3] = 1; + memcpy (temp + *destsize + 4, source, nal_len); + if (dest) + free(dest); + *destsize = tempsize; + + return temp; +} + + // decode a frame static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ int got_picture=0; @@ -687,6 +726,7 @@ AVCodecContext *avctx = ctx->avctx; mp_image_t* mpi=NULL; int dr1= ctx->do_dr1; + unsigned char *buf = NULL; if(len<=0) return NULL; // skipped frame @@ -736,8 +776,68 @@ data+= sizeof(dp_hdr_t); } + /* + * Convert avc1 nals to annexb nals (remove lenght, add sync) + * If first frame extract and process avcC (configuration data) + */ + if(sh->format == mmioFOURCC('a', 'v', 'c', '1')) { + int bufsize = 0; + int nalsize; + unsigned char *p = data; + int i; + int cnt, poffs; + + // Remember original values + ctx->data_bak = data; + ctx->len_bak = len; + + if (!ctx->got_avcC) { + // Parse some parts of avcC, just for fun :) + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC version: %d\n", *(p)); + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC profile: %d\n", *(p+1)); + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC profile compatibility: %d\n", *(p+2)); + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC level: %d\n", *(p+3)); + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC nal length size: %d\n", ctx->nal_length_size = ((*(p+4))&0x03)+1); + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC number of sequence param sets: %d\n", cnt = (*(p+5) & 0x1f)); + poffs = 6; + for (i = 0; i < cnt; i++) { + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC sps %d have length %d\n", i, nalsize = BE_16(p+poffs)); + buf = avc1_addnal(buf, &bufsize, p + poffs + 2, nalsize); + poffs += nalsize + 2; + } + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC number of picture param sets: %d\n", *(p+poffs)); + poffs++; + for (i = 0; i < cnt; i++) { + mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] avcC pps %d have length %d\n", i, nalsize = BE_16(p+poffs)); + buf = avc1_addnal(buf, &bufsize, p + poffs + 2, nalsize); + poffs += nalsize + 2; + } + p += poffs; + ctx->got_avcC = 1; + } + + while (p < (data + len)) { + nalsize = 0; + for(i = 0; i < ctx->nal_length_size; i++) + nalsize = (nalsize << 8) | (*p++); + mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "[ffmpeg] avc1: nalsize = %d\n", nalsize); + buf = avc1_addnal(buf, &bufsize, p, nalsize); + p += nalsize; + len -= nalsize; + } + data = buf; + len = bufsize; + } + ret = avcodec_decode_video(avctx, pic, &got_picture, data, len); + + if(sh->format == mmioFOURCC('a', 'v', 'c', '1')) { + free(buf); + data = ctx->data_bak; + len = ctx->len_bak; + } + dr1= ctx->do_dr1; if(ret<0) mp_msg(MSGT_DECVIDEO,MSGL_WARN, "Error while decoding frame!\n"); //printf("repeat: %d\n", pic->repeat_pict);