[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