• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/ffmdec.c

Go to the documentation of this file.
00001 /*
00002  * FFM (ffserver live feed) demuxer
00003  * Copyright (c) 2001 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/intfloat.h"
00024 #include "avformat.h"
00025 #include "internal.h"
00026 #include "ffm.h"
00027 #if CONFIG_FFSERVER
00028 #include <unistd.h>
00029 
00030 int64_t ffm_read_write_index(int fd)
00031 {
00032     uint8_t buf[8];
00033 
00034     lseek(fd, 8, SEEK_SET);
00035     if (read(fd, buf, 8) != 8)
00036         return AVERROR(EIO);
00037     return AV_RB64(buf);
00038 }
00039 
00040 int ffm_write_write_index(int fd, int64_t pos)
00041 {
00042     uint8_t buf[8];
00043     int i;
00044 
00045     for(i=0;i<8;i++)
00046         buf[i] = (pos >> (56 - i * 8)) & 0xff;
00047     lseek(fd, 8, SEEK_SET);
00048     if (write(fd, buf, 8) != 8)
00049         return AVERROR(EIO);
00050     return 8;
00051 }
00052 
00053 void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
00054 {
00055     FFMContext *ffm = s->priv_data;
00056     ffm->write_index = pos;
00057     ffm->file_size = file_size;
00058 }
00059 #endif // CONFIG_FFSERVER
00060 
00061 static int ffm_is_avail_data(AVFormatContext *s, int size)
00062 {
00063     FFMContext *ffm = s->priv_data;
00064     int64_t pos, avail_size;
00065     int len;
00066 
00067     len = ffm->packet_end - ffm->packet_ptr;
00068     if (size <= len)
00069         return 1;
00070     pos = avio_tell(s->pb);
00071     if (!ffm->write_index) {
00072         if (pos == ffm->file_size)
00073             return AVERROR_EOF;
00074         avail_size = ffm->file_size - pos;
00075     } else {
00076     if (pos == ffm->write_index) {
00077         /* exactly at the end of stream */
00078         return AVERROR(EAGAIN);
00079     } else if (pos < ffm->write_index) {
00080         avail_size = ffm->write_index - pos;
00081     } else {
00082         avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
00083     }
00084     }
00085     avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
00086     if (size <= avail_size)
00087         return 1;
00088     else
00089         return AVERROR(EAGAIN);
00090 }
00091 
00092 static int ffm_resync(AVFormatContext *s, int state)
00093 {
00094     av_log(s, AV_LOG_ERROR, "resyncing\n");
00095     while (state != PACKET_ID) {
00096         if (url_feof(s->pb)) {
00097             av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n");
00098             return -1;
00099         }
00100         state = (state << 8) | avio_r8(s->pb);
00101     }
00102     return 0;
00103 }
00104 
00105 /* first is true if we read the frame header */
00106 static int ffm_read_data(AVFormatContext *s,
00107                          uint8_t *buf, int size, int header)
00108 {
00109     FFMContext *ffm = s->priv_data;
00110     AVIOContext *pb = s->pb;
00111     int len, fill_size, size1, frame_offset, id;
00112 
00113     size1 = size;
00114     while (size > 0) {
00115     redo:
00116         len = ffm->packet_end - ffm->packet_ptr;
00117         if (len < 0)
00118             return -1;
00119         if (len > size)
00120             len = size;
00121         if (len == 0) {
00122             if (avio_tell(pb) == ffm->file_size)
00123                 avio_seek(pb, ffm->packet_size, SEEK_SET);
00124     retry_read:
00125             if (pb->buffer_size != ffm->packet_size) {
00126                 int64_t tell = avio_tell(pb);
00127                 url_setbufsize(pb, ffm->packet_size);
00128                 avio_seek(pb, tell, SEEK_SET);
00129             }
00130             id = avio_rb16(pb); /* PACKET_ID */
00131             if (id != PACKET_ID)
00132                 if (ffm_resync(s, id) < 0)
00133                     return -1;
00134             fill_size = avio_rb16(pb);
00135             ffm->dts = avio_rb64(pb);
00136             frame_offset = avio_rb16(pb);
00137             avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
00138             ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
00139             if (ffm->packet_end < ffm->packet || frame_offset < 0)
00140                 return -1;
00141             /* if first packet or resynchronization packet, we must
00142                handle it specifically */
00143             if (ffm->first_packet || (frame_offset & 0x8000)) {
00144                 if (!frame_offset) {
00145                     /* This packet has no frame headers in it */
00146                     if (avio_tell(pb) >= ffm->packet_size * 3) {
00147                         avio_seek(pb, -ffm->packet_size * 2, SEEK_CUR);
00148                         goto retry_read;
00149                     }
00150                     /* This is bad, we cannot find a valid frame header */
00151                     return 0;
00152                 }
00153                 ffm->first_packet = 0;
00154                 if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE)
00155                     return -1;
00156                 ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
00157                 if (!header)
00158                     break;
00159             } else {
00160                 ffm->packet_ptr = ffm->packet;
00161             }
00162             goto redo;
00163         }
00164         memcpy(buf, ffm->packet_ptr, len);
00165         buf += len;
00166         ffm->packet_ptr += len;
00167         size -= len;
00168         header = 0;
00169     }
00170     return size1 - size;
00171 }
00172 
00173 /* ensure that acutal seeking happens between FFM_PACKET_SIZE
00174    and file_size - FFM_PACKET_SIZE */
00175 static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1)
00176 {
00177     FFMContext *ffm = s->priv_data;
00178     AVIOContext *pb = s->pb;
00179     int64_t pos;
00180 
00181     pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE);
00182     pos = FFMAX(pos, FFM_PACKET_SIZE);
00183     av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
00184     return avio_seek(pb, pos, SEEK_SET);
00185 }
00186 
00187 static int64_t get_dts(AVFormatContext *s, int64_t pos)
00188 {
00189     AVIOContext *pb = s->pb;
00190     int64_t dts;
00191 
00192     ffm_seek1(s, pos);
00193     avio_skip(pb, 4);
00194     dts = avio_rb64(pb);
00195     av_dlog(s, "dts=%0.6f\n", dts / 1000000.0);
00196     return dts;
00197 }
00198 
00199 static void adjust_write_index(AVFormatContext *s)
00200 {
00201     FFMContext *ffm = s->priv_data;
00202     AVIOContext *pb = s->pb;
00203     int64_t pts;
00204     //int64_t orig_write_index = ffm->write_index;
00205     int64_t pos_min, pos_max;
00206     int64_t pts_start;
00207     int64_t ptr = avio_tell(pb);
00208 
00209 
00210     pos_min = 0;
00211     pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
00212 
00213     pts_start = get_dts(s, pos_min);
00214 
00215     pts = get_dts(s, pos_max);
00216 
00217     if (pts - 100000 > pts_start)
00218         goto end;
00219 
00220     ffm->write_index = FFM_PACKET_SIZE;
00221 
00222     pts_start = get_dts(s, pos_min);
00223 
00224     pts = get_dts(s, pos_max);
00225 
00226     if (pts - 100000 <= pts_start) {
00227         while (1) {
00228             int64_t newpos;
00229             int64_t newpts;
00230 
00231             newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
00232 
00233             if (newpos == pos_min)
00234                 break;
00235 
00236             newpts = get_dts(s, newpos);
00237 
00238             if (newpts - 100000 <= pts) {
00239                 pos_max = newpos;
00240                 pts = newpts;
00241             } else {
00242                 pos_min = newpos;
00243             }
00244         }
00245         ffm->write_index += pos_max;
00246     }
00247 
00248     //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
00249     //printf("pts range %0.6f - %0.6f\n", get_dts(s, 0) / 1000000. , get_dts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. );
00250 
00251  end:
00252     avio_seek(pb, ptr, SEEK_SET);
00253 }
00254 
00255 
00256 static int ffm_close(AVFormatContext *s)
00257 {
00258     int i;
00259 
00260     for (i = 0; i < s->nb_streams; i++)
00261         av_freep(&s->streams[i]->codec->rc_eq);
00262 
00263     return 0;
00264 }
00265 
00266 
00267 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
00268 {
00269     FFMContext *ffm = s->priv_data;
00270     AVStream *st;
00271     AVIOContext *pb = s->pb;
00272     AVCodecContext *codec;
00273     int i, nb_streams;
00274     uint32_t tag;
00275 
00276     /* header */
00277     tag = avio_rl32(pb);
00278     if (tag != MKTAG('F', 'F', 'M', '1'))
00279         goto fail;
00280     ffm->packet_size = avio_rb32(pb);
00281     if (ffm->packet_size != FFM_PACKET_SIZE)
00282         goto fail;
00283     ffm->write_index = avio_rb64(pb);
00284     /* get also filesize */
00285     if (pb->seekable) {
00286         ffm->file_size = avio_size(pb);
00287         if (ffm->write_index)
00288             adjust_write_index(s);
00289     } else {
00290         ffm->file_size = (UINT64_C(1) << 63) - 1;
00291     }
00292 
00293     nb_streams = avio_rb32(pb);
00294     avio_rb32(pb); /* total bitrate */
00295     /* read each stream */
00296     for(i=0;i<nb_streams;i++) {
00297         char rc_eq_buf[128];
00298 
00299         st = avformat_new_stream(s, NULL);
00300         if (!st)
00301             goto fail;
00302 
00303         avpriv_set_pts_info(st, 64, 1, 1000000);
00304 
00305         codec = st->codec;
00306         /* generic info */
00307         codec->codec_id = avio_rb32(pb);
00308         codec->codec_type = avio_r8(pb); /* codec_type */
00309         codec->bit_rate = avio_rb32(pb);
00310         codec->flags = avio_rb32(pb);
00311         codec->flags2 = avio_rb32(pb);
00312         codec->debug = avio_rb32(pb);
00313         /* specific info */
00314         switch(codec->codec_type) {
00315         case AVMEDIA_TYPE_VIDEO:
00316             codec->time_base.num = avio_rb32(pb);
00317             codec->time_base.den = avio_rb32(pb);
00318             codec->width = avio_rb16(pb);
00319             codec->height = avio_rb16(pb);
00320             codec->gop_size = avio_rb16(pb);
00321             codec->pix_fmt = avio_rb32(pb);
00322             codec->qmin = avio_r8(pb);
00323             codec->qmax = avio_r8(pb);
00324             codec->max_qdiff = avio_r8(pb);
00325             codec->qcompress = avio_rb16(pb) / 10000.0;
00326             codec->qblur = avio_rb16(pb) / 10000.0;
00327             codec->bit_rate_tolerance = avio_rb32(pb);
00328             avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
00329             codec->rc_eq = av_strdup(rc_eq_buf);
00330             codec->rc_max_rate = avio_rb32(pb);
00331             codec->rc_min_rate = avio_rb32(pb);
00332             codec->rc_buffer_size = avio_rb32(pb);
00333             codec->i_quant_factor = av_int2double(avio_rb64(pb));
00334             codec->b_quant_factor = av_int2double(avio_rb64(pb));
00335             codec->i_quant_offset = av_int2double(avio_rb64(pb));
00336             codec->b_quant_offset = av_int2double(avio_rb64(pb));
00337             codec->dct_algo = avio_rb32(pb);
00338             codec->strict_std_compliance = avio_rb32(pb);
00339             codec->max_b_frames = avio_rb32(pb);
00340             codec->luma_elim_threshold = avio_rb32(pb);
00341             codec->chroma_elim_threshold = avio_rb32(pb);
00342             codec->mpeg_quant = avio_rb32(pb);
00343             codec->intra_dc_precision = avio_rb32(pb);
00344             codec->me_method = avio_rb32(pb);
00345             codec->mb_decision = avio_rb32(pb);
00346             codec->nsse_weight = avio_rb32(pb);
00347             codec->frame_skip_cmp = avio_rb32(pb);
00348             codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
00349             codec->codec_tag = avio_rb32(pb);
00350             codec->thread_count = avio_r8(pb);
00351             codec->coder_type = avio_rb32(pb);
00352             codec->me_cmp = avio_rb32(pb);
00353             codec->partitions = avio_rb32(pb);
00354             codec->me_subpel_quality = avio_rb32(pb);
00355             codec->me_range = avio_rb32(pb);
00356             codec->keyint_min = avio_rb32(pb);
00357             codec->scenechange_threshold = avio_rb32(pb);
00358             codec->b_frame_strategy = avio_rb32(pb);
00359             codec->qcompress = av_int2double(avio_rb64(pb));
00360             codec->qblur = av_int2double(avio_rb64(pb));
00361             codec->max_qdiff = avio_rb32(pb);
00362             codec->refs = avio_rb32(pb);
00363             codec->directpred = avio_rb32(pb);
00364             break;
00365         case AVMEDIA_TYPE_AUDIO:
00366             codec->sample_rate = avio_rb32(pb);
00367             codec->channels = avio_rl16(pb);
00368             codec->frame_size = avio_rl16(pb);
00369             codec->sample_fmt = (int16_t) avio_rl16(pb);
00370             break;
00371         default:
00372             goto fail;
00373         }
00374         if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
00375             codec->extradata_size = avio_rb32(pb);
00376             codec->extradata = av_malloc(codec->extradata_size);
00377             if (!codec->extradata)
00378                 return AVERROR(ENOMEM);
00379             avio_read(pb, codec->extradata, codec->extradata_size);
00380         }
00381     }
00382 
00383     /* get until end of block reached */
00384     while ((avio_tell(pb) % ffm->packet_size) != 0)
00385         avio_r8(pb);
00386 
00387     /* init packet demux */
00388     ffm->packet_ptr = ffm->packet;
00389     ffm->packet_end = ffm->packet;
00390     ffm->frame_offset = 0;
00391     ffm->dts = 0;
00392     ffm->read_state = READ_HEADER;
00393     ffm->first_packet = 1;
00394     return 0;
00395  fail:
00396     ffm_close(s);
00397     return -1;
00398 }
00399 
00400 /* return < 0 if eof */
00401 static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
00402 {
00403     int size;
00404     FFMContext *ffm = s->priv_data;
00405     int duration, ret;
00406 
00407     switch(ffm->read_state) {
00408     case READ_HEADER:
00409         if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0)
00410             return ret;
00411 
00412         av_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
00413                avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size);
00414         if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
00415             FRAME_HEADER_SIZE)
00416             return -1;
00417         if (ffm->header[1] & FLAG_DTS)
00418             if (ffm_read_data(s, ffm->header+16, 4, 1) != 4)
00419                 return -1;
00420         ffm->read_state = READ_DATA;
00421         /* fall thru */
00422     case READ_DATA:
00423         size = AV_RB24(ffm->header + 2);
00424         if ((ret = ffm_is_avail_data(s, size)) < 0)
00425             return ret;
00426 
00427         duration = AV_RB24(ffm->header + 5);
00428 
00429         av_new_packet(pkt, size);
00430         pkt->stream_index = ffm->header[0];
00431         if ((unsigned)pkt->stream_index >= s->nb_streams) {
00432             av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index);
00433             av_free_packet(pkt);
00434             ffm->read_state = READ_HEADER;
00435             return -1;
00436         }
00437         pkt->pos = avio_tell(s->pb);
00438         if (ffm->header[1] & FLAG_KEY_FRAME)
00439             pkt->flags |= AV_PKT_FLAG_KEY;
00440 
00441         ffm->read_state = READ_HEADER;
00442         if (ffm_read_data(s, pkt->data, size, 0) != size) {
00443             /* bad case: desynchronized packet. we cancel all the packet loading */
00444             av_free_packet(pkt);
00445             return -1;
00446         }
00447         pkt->pts = AV_RB64(ffm->header+8);
00448         if (ffm->header[1] & FLAG_DTS)
00449             pkt->dts = pkt->pts - AV_RB32(ffm->header+16);
00450         else
00451             pkt->dts = pkt->pts;
00452         pkt->duration = duration;
00453         break;
00454     }
00455     return 0;
00456 }
00457 
00458 /* seek to a given time in the file. The file read pointer is
00459    positioned at or before pts. XXX: the following code is quite
00460    approximative */
00461 static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
00462 {
00463     FFMContext *ffm = s->priv_data;
00464     int64_t pos_min, pos_max, pos;
00465     int64_t pts_min, pts_max, pts;
00466     double pos1;
00467 
00468     av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
00469     /* find the position using linear interpolation (better than
00470        dichotomy in typical cases) */
00471     if (ffm->write_index && ffm->write_index < ffm->file_size) {
00472         if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) {
00473             pos_min = FFM_PACKET_SIZE;
00474             pos_max = ffm->write_index - FFM_PACKET_SIZE;
00475         } else {
00476             pos_min = ffm->write_index;
00477             pos_max = ffm->file_size - FFM_PACKET_SIZE;
00478         }
00479     } else {
00480         pos_min = FFM_PACKET_SIZE;
00481         pos_max = ffm->file_size - FFM_PACKET_SIZE;
00482     }
00483     while (pos_min <= pos_max) {
00484         pts_min = get_dts(s, pos_min);
00485         pts_max = get_dts(s, pos_max);
00486         if (pts_min > wanted_pts || pts_max < wanted_pts) {
00487             pos = pts_min > wanted_pts ? pos_min : pos_max;
00488             goto found;
00489         }
00490         /* linear interpolation */
00491         pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
00492             (double)(pts_max - pts_min);
00493         pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
00494         if (pos <= pos_min)
00495             pos = pos_min;
00496         else if (pos >= pos_max)
00497             pos = pos_max;
00498         pts = get_dts(s, pos);
00499         /* check if we are lucky */
00500         if (pts == wanted_pts) {
00501             goto found;
00502         } else if (pts > wanted_pts) {
00503             pos_max = pos - FFM_PACKET_SIZE;
00504         } else {
00505             pos_min = pos + FFM_PACKET_SIZE;
00506         }
00507     }
00508     pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
00509 
00510  found:
00511     if (ffm_seek1(s, pos) < 0)
00512         return -1;
00513 
00514     /* reset read state */
00515     ffm->read_state = READ_HEADER;
00516     ffm->packet_ptr = ffm->packet;
00517     ffm->packet_end = ffm->packet;
00518     ffm->first_packet = 1;
00519 
00520     return 0;
00521 }
00522 
00523 static int ffm_probe(AVProbeData *p)
00524 {
00525     if (
00526         p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
00527         p->buf[3] == '1')
00528         return AVPROBE_SCORE_MAX + 1;
00529     return 0;
00530 }
00531 
00532 AVInputFormat ff_ffm_demuxer = {
00533     .name           = "ffm",
00534     .long_name      = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed) format"),
00535     .priv_data_size = sizeof(FFMContext),
00536     .read_probe     = ffm_probe,
00537     .read_header    = ffm_read_header,
00538     .read_packet    = ffm_read_packet,
00539     .read_close     = ffm_close,
00540     .read_seek      = ffm_seek,
00541 };
Generated on Fri Feb 1 2013 14:34:51 for FFmpeg by doxygen 1.7.1