diff options
author | rtognimp <rtognimp@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2004-08-29 13:52:19 +0000 |
---|---|---|
committer | rtognimp <rtognimp@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2004-08-29 13:52:19 +0000 |
commit | b026fd05ae66ae78379a11efb5e4b5a93195dea1 (patch) | |
tree | 70f6fa0f6df5981d9f4752e03c8898814d41d677 | |
parent | f789226f32ce1733a6d0eb3d46b1354b1cbe7e64 (diff) |
AVC (fourcc avc1) in mp4 support
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@13191 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | etc/codecs.conf | 1 | ||||
-rw-r--r-- | libmpcodecs/vd_ffmpeg.c | 100 | ||||
-rw-r--r-- | libmpdemux/demux_mov.c | 33 |
3 files changed, 134 insertions, 0 deletions
diff --git a/etc/codecs.conf b/etc/codecs.conf index 297f8f9a08..2ed97fcd86 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -424,6 +424,7 @@ videocodec ffh264 info "FFmpeg H.264" status working fourcc H264,h264 + fourcc avc1 format 0x10000005 driver ffmpeg dll h264 diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c index 12567c4a25..fc76404020 100644 --- a/libmpcodecs/vd_ffmpeg.c +++ b/libmpcodecs/vd_ffmpeg.c @@ -72,6 +72,11 @@ typedef struct { 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 @@ static int init(sh_video_t *sh){ 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 @@ typedef struct dp_hdr_s { 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 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ 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 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ 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); diff --git a/libmpdemux/demux_mov.c b/libmpdemux/demux_mov.c index 4e878cff44..0156fd03e4 100644 --- a/libmpdemux/demux_mov.c +++ b/libmpdemux/demux_mov.c @@ -1111,6 +1111,39 @@ static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak mp4_free_esds(&esds); // freeup esds mem } break; + case MOV_FOURCC('a','v','c','C'): + // AVC decoder configuration record + mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); + if(atom_len > 8) { + int i, poffs, cnt; + // Parse some parts of avcC, just for fun :) + // avcC formatting happens in vd_ffmpeg, sps and pps are decoded in lavc + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); + if (*(trak->stdata+pos+8) != 1) + mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC nal length size: %d\n", (*(trak->stdata+pos+12))&0x03+1); + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); + poffs = pos + 14; + for (i = 0; i < cnt; i++) { + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); + poffs += BE_16(trak->stdata+poffs) + 2; + } + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); + poffs++; + for (i = 0; i < cnt; i++) { + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); + poffs += BE_16(trak->stdata+poffs) + 2; + } + // Copy avcC for the AVC decoder + // This data will be sent to decoder with first frame, before frame data + trak->stream_header_len = atom_len-8; + trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); + memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); + } + break; case 0: break; default: |