[FFmpeg-devel] rockplayer patches to ffmpeg

Kostya kostya.shishkov
Fri Feb 11 09:29:51 CET 2011


On Thu, Feb 10, 2011 at 05:33:27PM +0100, Vladimir Pantelic wrote:
> based on: http://rockplayer.freecoder.org/download/rockplayer_ffmpeg.zip
> 
> which itself seems to be based on SVN r22870

[...]
 
> apart from that, 3 patches:
> 
> 1) RM demuxer timestamp correction, seems to be based on mplayer's realdemux.c
> 
> 2) one rtsp error message changed
> 
> 3) some mangling of AAC/NEON support?!?!
> 
> 
> 
> 
> 

> diff -uwbr ffmpeg_svn/libavformat//rmdec.c rockplayer/libavformat//rmdec.c
> --- ffmpeg_svn/libavformat//rmdec.c	2011-02-10 16:44:19.000000000 +0100
> +++ rockplayer/libavformat//rmdec.c	2010-06-14 22:42:28.000000000 +0200
> @@ -47,6 +47,10 @@
>      int remaining_len;
>      int audio_stream_num; ///< Stream number for audio packets
>      int audio_pkt_cnt; ///< Output packet counter
> +
> +    int video_after_seek;
> +    int64_t kf_base;    ///< timestamp of the prev. video keyframe
> +    uint32_t kf_pts;    ///< timestamp of next video keyframe
>  } RMDemuxContext;
>  
>  static const AVCodecTag rm_codec_tags[] = {
> @@ -81,12 +85,76 @@
>  
>  const unsigned char ff_sipr_subpk_size[4] = { 29, 19, 37, 20 };
>  
> +#define RM_SKIP_BITS(n) buffer<<=n
> +#define RM_SHOW_BITS(n) ((buffer)>>(32-(n)))

It makes me want to rm it.

> +static int rm_fix_timestamp(uint8_t *buf, uint32_t timestamp, uint32_t format,
> +    int64_t *kf_base, int *kf_pts, int *pts)
> +{
> +    uint8_t *s = buf + 1 + (*buf+1)*8;
> +    uint32_t buffer = (s[0]<<24) + (s[1]<<16) + (s[2]<<8) + s[3];
> +    uint32_t kf = timestamp;
> +    int pict_type;
> +    uint32_t orig_kf;
> +
> +    if(format == MKTAG('R','V','3','0') || format == MKTAG('R','V','4','0')){
> +        if(format == MKTAG('R','V','3','0')){
> +            RM_SKIP_BITS(3);
> +            pict_type = RM_SHOW_BITS(2);
> +            RM_SKIP_BITS(2 + 7);
> +        }else{
> +            RM_SKIP_BITS(1);
> +            pict_type = RM_SHOW_BITS(2);
> +            RM_SKIP_BITS(2 + 7 + 3);
> +        }
> +        orig_kf = kf = RM_SHOW_BITS(13);  //    kf= 2*SHOW_BITS(12);
> +        if(pict_type <= 1){
> +            // I frame, sync timestamps:
> +            *kf_base = (int64_t)timestamp-kf;
> +            av_log(NULL, AV_LOG_DEBUG,"\nTS: base=%08"PRIX64"\n",*kf_base);
> +            kf = timestamp;
> +        } else {
> +            // P/B frame, merge timestamps:
> +            int64_t tmp = (int64_t)timestamp - *kf_base;
> +            kf |= tmp&(~0x1fff);    // combine with packet timestamp
> +            if(kf<tmp-4096) kf += 8192; else // workaround wrap-around problems
> +            if(kf>tmp+4096) kf -= 8192;

nice formatting

> +            kf += *kf_base;
> +        }
> +        if(pict_type != 3){ // P || I  frame -> swap timestamps
> +            uint32_t tmp=kf;
> +            kf = *kf_pts;
> +            *kf_pts = tmp;
> +        }
> +        av_log(NULL, AV_LOG_DEBUG,"\nTS: %08X -> %08X (%04X) %d %02X %02X %02X %02X %5u\n",
> +            timestamp,kf,orig_kf,pict_type,s[0],s[1],s[2],s[3],pts?kf-(*pts):0);
> +    }
> +    if(pts)
> +         *pts = kf;
> +    return kf;
> +}

in general it's not that bad though

> +static void process_video_timestamp(RMDemuxContext *rm, uint32_t codec_tag,AVPacket *pkt)
> +{
> +    //FIXME: it seems that only RV30 can deliver the braindamaged AV_NOPTS_VALUE
> +    if(pkt->pts == AV_NOPTS_VALUE)
> +        return;
> +    if(rm->video_after_seek){
> +        rm->kf_base = 0;
> +        rm->kf_pts = pkt->pts;
> +        rm->video_after_seek = 0;
> +    }
> +    pkt->pts = rm_fix_timestamp(pkt->data, pkt->pts,
> +                                     codec_tag,
> +                                     &rm->kf_base, &rm->kf_pts,
> +                                     NULL);
> +}

tastes like a wrapper

>  static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len)
>  {
>      int i;
> -    char *q, r;
> +    char *q = buf, r;
>  
> -    q = buf;

totally irrelevant change

>      for(i=0;i<len;i++) {
>          r = get_byte(pb);
>          if (i < buf_size - 1)
> @@ -141,51 +209,55 @@
>                                       AVStream *st, RMStream *ast, int read_all)
>  {
>      char buf[256];
> -    uint32_t version;
> +    uint32_t version,headsize;
>      int ret;
>  
>      /* ra type header */
>      version = get_be16(pb); /* version */
> +    headsize = get_be16(pb);
>      if (version == 3) {
> -        int header_size = get_be16(pb);
>          int64_t startpos = url_ftell(pb);
> +        int64_t headoffset = startpos + headsize;
> +
>          url_fskip(pb, 14);
>          rm_read_metadata(s, 0);
> -        if ((startpos + header_size) >= url_ftell(pb) + 2) {
> +        if (headoffset >= url_ftell(pb) + 2) {
>              // fourcc (should always be "lpcJ")
>              get_byte(pb);
>              get_str8(pb, buf, sizeof(buf));
>          }
>          // Skip extra header crap (this should never happen)
> -        if ((startpos + header_size) > url_ftell(pb))
> -            url_fskip(pb, header_size + startpos - url_ftell(pb));
> +        if (headoffset > url_ftell(pb))
> +            url_fskip(pb, headoffset - url_ftell(pb));
>          st->codec->sample_rate = 8000;
>          st->codec->channels = 1;
>          st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
>          st->codec->codec_id = CODEC_ID_RA_144;
>      } else {
> -        int flavor, sub_packet_h, coded_framesize, sub_packet_size;
> +        int flavor;
>          int codecdata_length;
>          /* old version (4) */
> -        url_fskip(pb, 2); /* unused */
>          get_be32(pb); /* .ra4 */
>          get_be32(pb); /* data size */
>          get_be16(pb); /* version2 */
>          get_be32(pb); /* header size */
>          flavor= get_be16(pb); /* add codec info / flavor */
> -        ast->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
> +        ast->coded_framesize = get_be32(pb); /* coded frame size */
>          get_be32(pb); /* ??? */
>          get_be32(pb); /* ??? */
>          get_be32(pb); /* ??? */
> -        ast->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
> +        ast->sub_packet_h = get_be16(pb); /* 1 */
>          st->codec->block_align= get_be16(pb); /* frame size */
> -        ast->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
> +        ast->sub_packet_size = get_be16(pb); /* sub packet size */
>          get_be16(pb); /* ??? */
>          if (version == 5) {
> -            get_be16(pb); get_be16(pb); get_be16(pb);
> +            get_be16(pb);
> +            get_be16(pb);
> +            get_be16(pb);
>          }
>          st->codec->sample_rate = get_be16(pb);
> -        get_be32(pb);
> +        get_be16(pb); /* ??? */
> +        get_be16(pb); /* sample size */
>          st->codec->channels = get_be16(pb);
>          if (version == 5) {
>              get_be32(pb);
> @@ -193,7 +265,7 @@
>              buf[4] = 0;
>          } else {
>              get_str8(pb, buf, sizeof(buf)); /* desc */
> -            get_str8(pb, buf, sizeof(buf)); /* desc */
> +            get_str8(pb, buf, sizeof(buf)); /* FOURCC */
>          }
>          st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
>          st->codec->codec_tag  = AV_RL32(buf);
> @@ -205,14 +277,14 @@
>          case CODEC_ID_RA_288:
>              st->codec->extradata_size= 0;
>              ast->audio_framesize = st->codec->block_align;
> -            st->codec->block_align = coded_framesize;
> +            st->codec->block_align = ast->coded_framesize;
>  
> -            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
> +            if(ast->audio_framesize >= UINT_MAX / ast->sub_packet_h){
>                  av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n");
>                  return -1;
>              }
>  
> -            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
> +            av_new_packet(&ast->pkt, ast->audio_framesize * ast->sub_packet_h);
>              break;
>          case CODEC_ID_COOK:
>          case CODEC_ID_ATRAC3:
> @@ -239,7 +311,7 @@
>                  }
>                  st->codec->block_align = ff_sipr_subpk_size[flavor];
>              } else {
> -                if(sub_packet_size <= 0){
> +                if(ast->sub_packet_size <= 0){
>                      av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
>                      return -1;
>                  }
> @@ -248,12 +320,12 @@
>              if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0)
>                  return ret;
>  
> -            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
> -                av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
> +            if(ast->audio_framesize >= UINT_MAX / ast->sub_packet_h){
> +                av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n");
>                  return -1;
>              }
>  
> -            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
> +            av_new_packet(&ast->pkt, ast->audio_framesize * ast->sub_packet_h);
>              break;
>          case CODEC_ID_AAC:
>              get_be16(pb); get_byte(pb);

These chunks are for different issue (but it may be useful anyway).

> @@ -301,10 +373,11 @@
>          if (rm_read_audio_stream_info(s, pb, st, rst, 0))
>              return -1;
>      } else {
> -        int fps, fps2;
> +        int gcd, fps;
>          if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
>          fail1:
>              av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
> +            st->codec->codec_id = CODEC_ID_NONE; //FIXME
>              goto skip;
>          }
>          st->codec->codec_tag = get_le32(pb);
> @@ -314,18 +387,19 @@
>              goto fail1;
>          st->codec->width = get_be16(pb);
>          st->codec->height = get_be16(pb);
> -        st->codec->time_base.num= 1;
> -        fps= get_be16(pb);
> +        st->codec->time_base.num= 1 << 16;
> +        get_be16(pb);/* bpp */
>          st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
>          get_be32(pb);
> -        fps2= get_be16(pb);
> -        get_be16(pb);
> +        fps= get_be32(pb);
>  
>          if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (url_ftell(pb) - codec_pos))) < 0)
>              return ret;
>  
> -//        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
> -        st->codec->time_base.den = fps * st->codec->time_base.num;
> +        st->codec->time_base.den = fps;
> +        gcd = av_gcd(st->codec->time_base.num, st->codec->time_base.den);
> +        st->codec->time_base.num /= gcd;
> +        st->codec->time_base.den /= gcd;
>          //XXX: do we really need that?
>          switch(st->codec->extradata[4]>>4){
>          case 1: st->codec->codec_id = CODEC_ID_RV10; break;

This too. Damn, we need RM format specs.

> @@ -389,7 +463,7 @@
>  
>      return 0;
>  }
> -
> +/* audio data is CBR */
>  static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
>  {
>      RMDemuxContext *rm = s->priv_data;
> @@ -408,9 +482,8 @@
>      RMDemuxContext *rm = s->priv_data;
>      AVStream *st;
>      ByteIOContext *pb = s->pb;
> -    unsigned int tag;
> +    unsigned int tag, head_size;
>      int tag_size;
> -    unsigned int start_time, duration;
>      unsigned int data_off = 0, indx_off = 0;
>      char buf[128];
>      int flags = 0;
> @@ -423,9 +496,13 @@
>          return AVERROR(EIO);
>      }
>  
> -    get_be32(pb); /* header size */
> -    get_be16(pb);
> +    head_size = get_be32(pb); /* including 8-bytes preamble */
> +    get_be16(pb); /* chunk version */
> +    /* file version */
> +    if(0x12 == head_size)
>      get_be32(pb);
> +    else
> +        get_be16(pb);
>      get_be32(pb); /* number of headers */
>  
>      for(;;) {
> @@ -433,7 +510,7 @@
>              return -1;
>          tag = get_le32(pb);
>          tag_size = get_be32(pb);
> -        get_be16(pb);
> +        get_be16(pb); /* version */
>  #if 0
>          printf("tag=%c%c%c%c (%08x) size=%d\n",
>                 (tag) & 0xff,
> @@ -453,10 +530,10 @@
>              get_be32(pb); /* max packet size */
>              get_be32(pb); /* avg packet size */
>              get_be32(pb); /* nb packets */
> -            get_be32(pb); /* duration */
> -            get_be32(pb); /* preroll */
> -            indx_off = get_be32(pb); /* index offset */
> -            data_off = get_be32(pb); /* data offset */
> +            get_be32(pb); /* duration in ms */
> +            get_be32(pb); /* preroll in ms */
> +            indx_off = get_be32(pb); /* the first index offset */
> +            data_off = get_be32(pb); /* the first data offset */
>              get_be16(pb); /* nb streams */
>              flags = get_be16(pb); /* flags */
>              break;
> @@ -469,14 +546,12 @@
>                  return AVERROR(ENOMEM);
>              st->id = get_be16(pb);
>              get_be32(pb); /* max bit rate */
> -            st->codec->bit_rate = get_be32(pb); /* bit rate */
> +            st->codec->bit_rate = get_be32(pb); /* avg bit rate */
>              get_be32(pb); /* max packet size */
>              get_be32(pb); /* avg packet size */
> -            start_time = get_be32(pb); /* start time */
> -            get_be32(pb); /* preroll */
> -            duration = get_be32(pb); /* duration */
> -            st->start_time = start_time;
> -            st->duration = duration;
> +            st->start_time = get_be32(pb); /* start time in ms */
> +            get_be32(pb); /* preroll in ms */
> +            st->duration = get_be32(pb); /* duration in ms */
>              get_str8(pb, buf, sizeof(buf)); /* desc */
>              get_str8(pb, buf, sizeof(buf)); /* mimetype */
>              st->codec->codec_type = AVMEDIA_TYPE_DATA;
> @@ -793,7 +868,7 @@
>      if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
>          if(st->codec->codec_id == CODEC_ID_RV20){
>              int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
> -            av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq);
> +            av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", timestamp, timestamp*512LL/25, seq);
>  
>              seq |= (timestamp&~0x3FFF);
>              if(seq - timestamp >  0x2000) seq -= 0x4000;
> @@ -805,6 +880,8 @@
>      pkt->pts= timestamp;
>      if (flags & 2)
>          pkt->flags |= AV_PKT_FLAG_KEY;
> +    if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
> +        process_video_timestamp(rm,st->codec->codec_tag,pkt);
>  
>      return st->codec->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
>  }
> @@ -828,9 +905,9 @@
>      rm->audio_pkt_cnt--;
>      if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
>          ast->audiotimestamp = AV_NOPTS_VALUE;
> -        pkt->flags = AV_PKT_FLAG_KEY;
> +        pkt->flags |= AV_PKT_FLAG_KEY;
>      } else
> -        pkt->flags = 0;
> +        pkt->flags &= (~AV_PKT_FLAG_KEY);
>      pkt->stream_index = st->index;
>  
>      return rm->audio_pkt_cnt;
> @@ -951,6 +1028,7 @@
>          url_fskip(s->pb, len);
>      }
>      *ppos = pos;
> +    rm->video_after_seek = 1;
>      return dts;
>  }
>

Well, Ronald should untangle it before I can review it further. But looks like
there are quite a few promising things here.



More information about the ffmpeg-devel mailing list