annotate ffmpeg/libavformat/ffmdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * FFM (ffserver live feed) demuxer
yading@11 3 * Copyright (c) 2001 Fabrice Bellard
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 #include "libavutil/intreadwrite.h"
yading@11 23 #include "libavutil/intfloat.h"
yading@11 24 #include "avformat.h"
yading@11 25 #include "internal.h"
yading@11 26 #include "ffm.h"
yading@11 27 #include "avio_internal.h"
yading@11 28
yading@11 29 static int ffm_is_avail_data(AVFormatContext *s, int size)
yading@11 30 {
yading@11 31 FFMContext *ffm = s->priv_data;
yading@11 32 int64_t pos, avail_size;
yading@11 33 int len;
yading@11 34
yading@11 35 len = ffm->packet_end - ffm->packet_ptr;
yading@11 36 if (size <= len)
yading@11 37 return 1;
yading@11 38 pos = avio_tell(s->pb);
yading@11 39 if (!ffm->write_index) {
yading@11 40 if (pos == ffm->file_size)
yading@11 41 return AVERROR_EOF;
yading@11 42 avail_size = ffm->file_size - pos;
yading@11 43 } else {
yading@11 44 if (pos == ffm->write_index) {
yading@11 45 /* exactly at the end of stream */
yading@11 46 return AVERROR(EAGAIN);
yading@11 47 } else if (pos < ffm->write_index) {
yading@11 48 avail_size = ffm->write_index - pos;
yading@11 49 } else {
yading@11 50 avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
yading@11 51 }
yading@11 52 }
yading@11 53 avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
yading@11 54 if (size <= avail_size)
yading@11 55 return 1;
yading@11 56 else
yading@11 57 return AVERROR(EAGAIN);
yading@11 58 }
yading@11 59
yading@11 60 static int ffm_resync(AVFormatContext *s, int state)
yading@11 61 {
yading@11 62 av_log(s, AV_LOG_ERROR, "resyncing\n");
yading@11 63 while (state != PACKET_ID) {
yading@11 64 if (url_feof(s->pb)) {
yading@11 65 av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n");
yading@11 66 return -1;
yading@11 67 }
yading@11 68 state = (state << 8) | avio_r8(s->pb);
yading@11 69 }
yading@11 70 return 0;
yading@11 71 }
yading@11 72
yading@11 73 /* first is true if we read the frame header */
yading@11 74 static int ffm_read_data(AVFormatContext *s,
yading@11 75 uint8_t *buf, int size, int header)
yading@11 76 {
yading@11 77 FFMContext *ffm = s->priv_data;
yading@11 78 AVIOContext *pb = s->pb;
yading@11 79 int len, fill_size, size1, frame_offset, id;
yading@11 80
yading@11 81 size1 = size;
yading@11 82 while (size > 0) {
yading@11 83 redo:
yading@11 84 len = ffm->packet_end - ffm->packet_ptr;
yading@11 85 if (len < 0)
yading@11 86 return -1;
yading@11 87 if (len > size)
yading@11 88 len = size;
yading@11 89 if (len == 0) {
yading@11 90 if (avio_tell(pb) == ffm->file_size)
yading@11 91 avio_seek(pb, ffm->packet_size, SEEK_SET);
yading@11 92 retry_read:
yading@11 93 if (pb->buffer_size != ffm->packet_size) {
yading@11 94 int64_t tell = avio_tell(pb);
yading@11 95 ffio_set_buf_size(pb, ffm->packet_size);
yading@11 96 avio_seek(pb, tell, SEEK_SET);
yading@11 97 }
yading@11 98 id = avio_rb16(pb); /* PACKET_ID */
yading@11 99 if (id != PACKET_ID)
yading@11 100 if (ffm_resync(s, id) < 0)
yading@11 101 return -1;
yading@11 102 fill_size = avio_rb16(pb);
yading@11 103 ffm->dts = avio_rb64(pb);
yading@11 104 frame_offset = avio_rb16(pb);
yading@11 105 avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
yading@11 106 ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
yading@11 107 if (ffm->packet_end < ffm->packet || frame_offset < 0)
yading@11 108 return -1;
yading@11 109 /* if first packet or resynchronization packet, we must
yading@11 110 handle it specifically */
yading@11 111 if (ffm->first_packet || (frame_offset & 0x8000)) {
yading@11 112 if (!frame_offset) {
yading@11 113 /* This packet has no frame headers in it */
yading@11 114 if (avio_tell(pb) >= ffm->packet_size * 3LL) {
yading@11 115 avio_seek(pb, -ffm->packet_size * 2LL, SEEK_CUR);
yading@11 116 goto retry_read;
yading@11 117 }
yading@11 118 /* This is bad, we cannot find a valid frame header */
yading@11 119 return 0;
yading@11 120 }
yading@11 121 ffm->first_packet = 0;
yading@11 122 if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE)
yading@11 123 return -1;
yading@11 124 ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
yading@11 125 if (!header)
yading@11 126 break;
yading@11 127 } else {
yading@11 128 ffm->packet_ptr = ffm->packet;
yading@11 129 }
yading@11 130 goto redo;
yading@11 131 }
yading@11 132 memcpy(buf, ffm->packet_ptr, len);
yading@11 133 buf += len;
yading@11 134 ffm->packet_ptr += len;
yading@11 135 size -= len;
yading@11 136 header = 0;
yading@11 137 }
yading@11 138 return size1 - size;
yading@11 139 }
yading@11 140
yading@11 141 /* ensure that acutal seeking happens between FFM_PACKET_SIZE
yading@11 142 and file_size - FFM_PACKET_SIZE */
yading@11 143 static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1)
yading@11 144 {
yading@11 145 FFMContext *ffm = s->priv_data;
yading@11 146 AVIOContext *pb = s->pb;
yading@11 147 int64_t pos;
yading@11 148
yading@11 149 pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE);
yading@11 150 pos = FFMAX(pos, FFM_PACKET_SIZE);
yading@11 151 av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
yading@11 152 return avio_seek(pb, pos, SEEK_SET);
yading@11 153 }
yading@11 154
yading@11 155 static int64_t get_dts(AVFormatContext *s, int64_t pos)
yading@11 156 {
yading@11 157 AVIOContext *pb = s->pb;
yading@11 158 int64_t dts;
yading@11 159
yading@11 160 ffm_seek1(s, pos);
yading@11 161 avio_skip(pb, 4);
yading@11 162 dts = avio_rb64(pb);
yading@11 163 av_dlog(s, "dts=%0.6f\n", dts / 1000000.0);
yading@11 164 return dts;
yading@11 165 }
yading@11 166
yading@11 167 static void adjust_write_index(AVFormatContext *s)
yading@11 168 {
yading@11 169 FFMContext *ffm = s->priv_data;
yading@11 170 AVIOContext *pb = s->pb;
yading@11 171 int64_t pts;
yading@11 172 //int64_t orig_write_index = ffm->write_index;
yading@11 173 int64_t pos_min, pos_max;
yading@11 174 int64_t pts_start;
yading@11 175 int64_t ptr = avio_tell(pb);
yading@11 176
yading@11 177
yading@11 178 pos_min = 0;
yading@11 179 pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
yading@11 180
yading@11 181 pts_start = get_dts(s, pos_min);
yading@11 182
yading@11 183 pts = get_dts(s, pos_max);
yading@11 184
yading@11 185 if (pts - 100000 > pts_start)
yading@11 186 goto end;
yading@11 187
yading@11 188 ffm->write_index = FFM_PACKET_SIZE;
yading@11 189
yading@11 190 pts_start = get_dts(s, pos_min);
yading@11 191
yading@11 192 pts = get_dts(s, pos_max);
yading@11 193
yading@11 194 if (pts - 100000 <= pts_start) {
yading@11 195 while (1) {
yading@11 196 int64_t newpos;
yading@11 197 int64_t newpts;
yading@11 198
yading@11 199 newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
yading@11 200
yading@11 201 if (newpos == pos_min)
yading@11 202 break;
yading@11 203
yading@11 204 newpts = get_dts(s, newpos);
yading@11 205
yading@11 206 if (newpts - 100000 <= pts) {
yading@11 207 pos_max = newpos;
yading@11 208 pts = newpts;
yading@11 209 } else {
yading@11 210 pos_min = newpos;
yading@11 211 }
yading@11 212 }
yading@11 213 ffm->write_index += pos_max;
yading@11 214 }
yading@11 215
yading@11 216 end:
yading@11 217 avio_seek(pb, ptr, SEEK_SET);
yading@11 218 }
yading@11 219
yading@11 220
yading@11 221 static int ffm_close(AVFormatContext *s)
yading@11 222 {
yading@11 223 int i;
yading@11 224
yading@11 225 for (i = 0; i < s->nb_streams; i++)
yading@11 226 av_freep(&s->streams[i]->codec->rc_eq);
yading@11 227
yading@11 228 return 0;
yading@11 229 }
yading@11 230
yading@11 231 static int ffm2_read_header(AVFormatContext *s)
yading@11 232 {
yading@11 233 FFMContext *ffm = s->priv_data;
yading@11 234 AVStream *st;
yading@11 235 AVIOContext *pb = s->pb;
yading@11 236 AVCodecContext *codec;
yading@11 237
yading@11 238 ffm->packet_size = avio_rb32(pb);
yading@11 239 if (ffm->packet_size != FFM_PACKET_SIZE)
yading@11 240 goto fail;
yading@11 241 ffm->write_index = avio_rb64(pb);
yading@11 242 /* get also filesize */
yading@11 243 if (pb->seekable) {
yading@11 244 ffm->file_size = avio_size(pb);
yading@11 245 if (ffm->write_index && 0)
yading@11 246 adjust_write_index(s);
yading@11 247 } else {
yading@11 248 ffm->file_size = (UINT64_C(1) << 63) - 1;
yading@11 249 }
yading@11 250
yading@11 251 while(!url_feof(pb)) {
yading@11 252 unsigned id = avio_rb32(pb);
yading@11 253 unsigned size = avio_rb32(pb);
yading@11 254 int64_t next = avio_tell(pb) + size;
yading@11 255 char rc_eq_buf[128];
yading@11 256
yading@11 257 if(!id)
yading@11 258 break;
yading@11 259
yading@11 260 switch(id) {
yading@11 261 case MKBETAG('M', 'A', 'I', 'N'):
yading@11 262 avio_rb32(pb); /* nb_streams */
yading@11 263 avio_rb32(pb); /* total bitrate */
yading@11 264 break;
yading@11 265 case MKBETAG('C', 'O', 'M', 'M'):
yading@11 266 st = avformat_new_stream(s, NULL);
yading@11 267 if (!st)
yading@11 268 goto fail;
yading@11 269
yading@11 270 avpriv_set_pts_info(st, 64, 1, 1000000);
yading@11 271
yading@11 272 codec = st->codec;
yading@11 273 /* generic info */
yading@11 274 codec->codec_id = avio_rb32(pb);
yading@11 275 codec->codec_type = avio_r8(pb);
yading@11 276 codec->bit_rate = avio_rb32(pb);
yading@11 277 codec->flags = avio_rb32(pb);
yading@11 278 codec->flags2 = avio_rb32(pb);
yading@11 279 codec->debug = avio_rb32(pb);
yading@11 280 if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
yading@11 281 codec->extradata_size = avio_rb32(pb);
yading@11 282 codec->extradata = av_malloc(codec->extradata_size);
yading@11 283 if (!codec->extradata)
yading@11 284 return AVERROR(ENOMEM);
yading@11 285 avio_read(pb, codec->extradata, codec->extradata_size);
yading@11 286 }
yading@11 287 avio_seek(pb, next, SEEK_SET);
yading@11 288 id = avio_rb32(pb);
yading@11 289 size = avio_rb32(pb);
yading@11 290 next = avio_tell(pb) + size;
yading@11 291 switch(id) {
yading@11 292 case MKBETAG('S', 'T', 'V', 'I'):
yading@11 293 codec->time_base.num = avio_rb32(pb);
yading@11 294 codec->time_base.den = avio_rb32(pb);
yading@11 295 codec->width = avio_rb16(pb);
yading@11 296 codec->height = avio_rb16(pb);
yading@11 297 codec->gop_size = avio_rb16(pb);
yading@11 298 codec->pix_fmt = avio_rb32(pb);
yading@11 299 codec->qmin = avio_r8(pb);
yading@11 300 codec->qmax = avio_r8(pb);
yading@11 301 codec->max_qdiff = avio_r8(pb);
yading@11 302 codec->qcompress = avio_rb16(pb) / 10000.0;
yading@11 303 codec->qblur = avio_rb16(pb) / 10000.0;
yading@11 304 codec->bit_rate_tolerance = avio_rb32(pb);
yading@11 305 avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
yading@11 306 codec->rc_eq = av_strdup(rc_eq_buf);
yading@11 307 codec->rc_max_rate = avio_rb32(pb);
yading@11 308 codec->rc_min_rate = avio_rb32(pb);
yading@11 309 codec->rc_buffer_size = avio_rb32(pb);
yading@11 310 codec->i_quant_factor = av_int2double(avio_rb64(pb));
yading@11 311 codec->b_quant_factor = av_int2double(avio_rb64(pb));
yading@11 312 codec->i_quant_offset = av_int2double(avio_rb64(pb));
yading@11 313 codec->b_quant_offset = av_int2double(avio_rb64(pb));
yading@11 314 codec->dct_algo = avio_rb32(pb);
yading@11 315 codec->strict_std_compliance = avio_rb32(pb);
yading@11 316 codec->max_b_frames = avio_rb32(pb);
yading@11 317 codec->mpeg_quant = avio_rb32(pb);
yading@11 318 codec->intra_dc_precision = avio_rb32(pb);
yading@11 319 codec->me_method = avio_rb32(pb);
yading@11 320 codec->mb_decision = avio_rb32(pb);
yading@11 321 codec->nsse_weight = avio_rb32(pb);
yading@11 322 codec->frame_skip_cmp = avio_rb32(pb);
yading@11 323 codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
yading@11 324 codec->codec_tag = avio_rb32(pb);
yading@11 325 codec->thread_count = avio_r8(pb);
yading@11 326 codec->coder_type = avio_rb32(pb);
yading@11 327 codec->me_cmp = avio_rb32(pb);
yading@11 328 codec->me_subpel_quality = avio_rb32(pb);
yading@11 329 codec->me_range = avio_rb32(pb);
yading@11 330 codec->keyint_min = avio_rb32(pb);
yading@11 331 codec->scenechange_threshold = avio_rb32(pb);
yading@11 332 codec->b_frame_strategy = avio_rb32(pb);
yading@11 333 codec->qcompress = av_int2double(avio_rb64(pb));
yading@11 334 codec->qblur = av_int2double(avio_rb64(pb));
yading@11 335 codec->max_qdiff = avio_rb32(pb);
yading@11 336 codec->refs = avio_rb32(pb);
yading@11 337 break;
yading@11 338 case MKBETAG('S', 'T', 'A', 'U'):
yading@11 339 codec->sample_rate = avio_rb32(pb);
yading@11 340 codec->channels = avio_rl16(pb);
yading@11 341 codec->frame_size = avio_rl16(pb);
yading@11 342 break;
yading@11 343 }
yading@11 344 break;
yading@11 345 }
yading@11 346 avio_seek(pb, next, SEEK_SET);
yading@11 347 }
yading@11 348
yading@11 349 /* get until end of block reached */
yading@11 350 while ((avio_tell(pb) % ffm->packet_size) != 0)
yading@11 351 avio_r8(pb);
yading@11 352
yading@11 353 /* init packet demux */
yading@11 354 ffm->packet_ptr = ffm->packet;
yading@11 355 ffm->packet_end = ffm->packet;
yading@11 356 ffm->frame_offset = 0;
yading@11 357 ffm->dts = 0;
yading@11 358 ffm->read_state = READ_HEADER;
yading@11 359 ffm->first_packet = 1;
yading@11 360 return 0;
yading@11 361 fail:
yading@11 362 ffm_close(s);
yading@11 363 return -1;
yading@11 364 }
yading@11 365
yading@11 366 static int ffm_read_header(AVFormatContext *s)
yading@11 367 {
yading@11 368 FFMContext *ffm = s->priv_data;
yading@11 369 AVStream *st;
yading@11 370 AVIOContext *pb = s->pb;
yading@11 371 AVCodecContext *codec;
yading@11 372 int i, nb_streams;
yading@11 373 uint32_t tag;
yading@11 374
yading@11 375 /* header */
yading@11 376 tag = avio_rl32(pb);
yading@11 377 if (tag == MKTAG('F', 'F', 'M', '2'))
yading@11 378 return ffm2_read_header(s);
yading@11 379 if (tag != MKTAG('F', 'F', 'M', '1'))
yading@11 380 goto fail;
yading@11 381 ffm->packet_size = avio_rb32(pb);
yading@11 382 if (ffm->packet_size != FFM_PACKET_SIZE)
yading@11 383 goto fail;
yading@11 384 ffm->write_index = avio_rb64(pb);
yading@11 385 /* get also filesize */
yading@11 386 if (pb->seekable) {
yading@11 387 ffm->file_size = avio_size(pb);
yading@11 388 if (ffm->write_index && 0)
yading@11 389 adjust_write_index(s);
yading@11 390 } else {
yading@11 391 ffm->file_size = (UINT64_C(1) << 63) - 1;
yading@11 392 }
yading@11 393
yading@11 394 nb_streams = avio_rb32(pb);
yading@11 395 avio_rb32(pb); /* total bitrate */
yading@11 396 /* read each stream */
yading@11 397 for(i=0;i<nb_streams;i++) {
yading@11 398 char rc_eq_buf[128];
yading@11 399
yading@11 400 st = avformat_new_stream(s, NULL);
yading@11 401 if (!st)
yading@11 402 goto fail;
yading@11 403
yading@11 404 avpriv_set_pts_info(st, 64, 1, 1000000);
yading@11 405
yading@11 406 codec = st->codec;
yading@11 407 /* generic info */
yading@11 408 codec->codec_id = avio_rb32(pb);
yading@11 409 codec->codec_type = avio_r8(pb); /* codec_type */
yading@11 410 codec->bit_rate = avio_rb32(pb);
yading@11 411 codec->flags = avio_rb32(pb);
yading@11 412 codec->flags2 = avio_rb32(pb);
yading@11 413 codec->debug = avio_rb32(pb);
yading@11 414 /* specific info */
yading@11 415 switch(codec->codec_type) {
yading@11 416 case AVMEDIA_TYPE_VIDEO:
yading@11 417 codec->time_base.num = avio_rb32(pb);
yading@11 418 codec->time_base.den = avio_rb32(pb);
yading@11 419 codec->width = avio_rb16(pb);
yading@11 420 codec->height = avio_rb16(pb);
yading@11 421 codec->gop_size = avio_rb16(pb);
yading@11 422 codec->pix_fmt = avio_rb32(pb);
yading@11 423 codec->qmin = avio_r8(pb);
yading@11 424 codec->qmax = avio_r8(pb);
yading@11 425 codec->max_qdiff = avio_r8(pb);
yading@11 426 codec->qcompress = avio_rb16(pb) / 10000.0;
yading@11 427 codec->qblur = avio_rb16(pb) / 10000.0;
yading@11 428 codec->bit_rate_tolerance = avio_rb32(pb);
yading@11 429 avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
yading@11 430 codec->rc_eq = av_strdup(rc_eq_buf);
yading@11 431 codec->rc_max_rate = avio_rb32(pb);
yading@11 432 codec->rc_min_rate = avio_rb32(pb);
yading@11 433 codec->rc_buffer_size = avio_rb32(pb);
yading@11 434 codec->i_quant_factor = av_int2double(avio_rb64(pb));
yading@11 435 codec->b_quant_factor = av_int2double(avio_rb64(pb));
yading@11 436 codec->i_quant_offset = av_int2double(avio_rb64(pb));
yading@11 437 codec->b_quant_offset = av_int2double(avio_rb64(pb));
yading@11 438 codec->dct_algo = avio_rb32(pb);
yading@11 439 codec->strict_std_compliance = avio_rb32(pb);
yading@11 440 codec->max_b_frames = avio_rb32(pb);
yading@11 441 codec->mpeg_quant = avio_rb32(pb);
yading@11 442 codec->intra_dc_precision = avio_rb32(pb);
yading@11 443 codec->me_method = avio_rb32(pb);
yading@11 444 codec->mb_decision = avio_rb32(pb);
yading@11 445 codec->nsse_weight = avio_rb32(pb);
yading@11 446 codec->frame_skip_cmp = avio_rb32(pb);
yading@11 447 codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
yading@11 448 codec->codec_tag = avio_rb32(pb);
yading@11 449 codec->thread_count = avio_r8(pb);
yading@11 450 codec->coder_type = avio_rb32(pb);
yading@11 451 codec->me_cmp = avio_rb32(pb);
yading@11 452 codec->me_subpel_quality = avio_rb32(pb);
yading@11 453 codec->me_range = avio_rb32(pb);
yading@11 454 codec->keyint_min = avio_rb32(pb);
yading@11 455 codec->scenechange_threshold = avio_rb32(pb);
yading@11 456 codec->b_frame_strategy = avio_rb32(pb);
yading@11 457 codec->qcompress = av_int2double(avio_rb64(pb));
yading@11 458 codec->qblur = av_int2double(avio_rb64(pb));
yading@11 459 codec->max_qdiff = avio_rb32(pb);
yading@11 460 codec->refs = avio_rb32(pb);
yading@11 461 break;
yading@11 462 case AVMEDIA_TYPE_AUDIO:
yading@11 463 codec->sample_rate = avio_rb32(pb);
yading@11 464 codec->channels = avio_rl16(pb);
yading@11 465 codec->frame_size = avio_rl16(pb);
yading@11 466 break;
yading@11 467 default:
yading@11 468 goto fail;
yading@11 469 }
yading@11 470 if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
yading@11 471 codec->extradata_size = avio_rb32(pb);
yading@11 472 codec->extradata = av_malloc(codec->extradata_size);
yading@11 473 if (!codec->extradata)
yading@11 474 return AVERROR(ENOMEM);
yading@11 475 avio_read(pb, codec->extradata, codec->extradata_size);
yading@11 476 }
yading@11 477 }
yading@11 478
yading@11 479 /* get until end of block reached */
yading@11 480 while ((avio_tell(pb) % ffm->packet_size) != 0)
yading@11 481 avio_r8(pb);
yading@11 482
yading@11 483 /* init packet demux */
yading@11 484 ffm->packet_ptr = ffm->packet;
yading@11 485 ffm->packet_end = ffm->packet;
yading@11 486 ffm->frame_offset = 0;
yading@11 487 ffm->dts = 0;
yading@11 488 ffm->read_state = READ_HEADER;
yading@11 489 ffm->first_packet = 1;
yading@11 490 return 0;
yading@11 491 fail:
yading@11 492 ffm_close(s);
yading@11 493 return -1;
yading@11 494 }
yading@11 495
yading@11 496 /* return < 0 if eof */
yading@11 497 static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 498 {
yading@11 499 int size;
yading@11 500 FFMContext *ffm = s->priv_data;
yading@11 501 int duration, ret;
yading@11 502
yading@11 503 switch(ffm->read_state) {
yading@11 504 case READ_HEADER:
yading@11 505 if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0)
yading@11 506 return ret;
yading@11 507
yading@11 508 av_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
yading@11 509 avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size);
yading@11 510 if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
yading@11 511 FRAME_HEADER_SIZE)
yading@11 512 return -1;
yading@11 513 if (ffm->header[1] & FLAG_DTS)
yading@11 514 if (ffm_read_data(s, ffm->header+16, 4, 1) != 4)
yading@11 515 return -1;
yading@11 516 ffm->read_state = READ_DATA;
yading@11 517 /* fall thru */
yading@11 518 case READ_DATA:
yading@11 519 size = AV_RB24(ffm->header + 2);
yading@11 520 if ((ret = ffm_is_avail_data(s, size)) < 0)
yading@11 521 return ret;
yading@11 522
yading@11 523 duration = AV_RB24(ffm->header + 5);
yading@11 524
yading@11 525 if (av_new_packet(pkt, size) < 0) {
yading@11 526 return AVERROR(ENOMEM);
yading@11 527 }
yading@11 528 pkt->stream_index = ffm->header[0];
yading@11 529 if ((unsigned)pkt->stream_index >= s->nb_streams) {
yading@11 530 av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index);
yading@11 531 av_free_packet(pkt);
yading@11 532 ffm->read_state = READ_HEADER;
yading@11 533 return -1;
yading@11 534 }
yading@11 535 pkt->pos = avio_tell(s->pb);
yading@11 536 if (ffm->header[1] & FLAG_KEY_FRAME)
yading@11 537 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 538
yading@11 539 ffm->read_state = READ_HEADER;
yading@11 540 if (ffm_read_data(s, pkt->data, size, 0) != size) {
yading@11 541 /* bad case: desynchronized packet. we cancel all the packet loading */
yading@11 542 av_free_packet(pkt);
yading@11 543 return -1;
yading@11 544 }
yading@11 545 pkt->pts = AV_RB64(ffm->header+8);
yading@11 546 if (ffm->header[1] & FLAG_DTS)
yading@11 547 pkt->dts = pkt->pts - AV_RB32(ffm->header+16);
yading@11 548 else
yading@11 549 pkt->dts = pkt->pts;
yading@11 550 pkt->duration = duration;
yading@11 551 break;
yading@11 552 }
yading@11 553 return 0;
yading@11 554 }
yading@11 555
yading@11 556 /* seek to a given time in the file. The file read pointer is
yading@11 557 positioned at or before pts. XXX: the following code is quite
yading@11 558 approximative */
yading@11 559 static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
yading@11 560 {
yading@11 561 FFMContext *ffm = s->priv_data;
yading@11 562 int64_t pos_min, pos_max, pos;
yading@11 563 int64_t pts_min, pts_max, pts;
yading@11 564 double pos1;
yading@11 565
yading@11 566 av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
yading@11 567 /* find the position using linear interpolation (better than
yading@11 568 dichotomy in typical cases) */
yading@11 569 if (ffm->write_index && ffm->write_index < ffm->file_size) {
yading@11 570 if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) {
yading@11 571 pos_min = FFM_PACKET_SIZE;
yading@11 572 pos_max = ffm->write_index - FFM_PACKET_SIZE;
yading@11 573 } else {
yading@11 574 pos_min = ffm->write_index;
yading@11 575 pos_max = ffm->file_size - FFM_PACKET_SIZE;
yading@11 576 }
yading@11 577 } else {
yading@11 578 pos_min = FFM_PACKET_SIZE;
yading@11 579 pos_max = ffm->file_size - FFM_PACKET_SIZE;
yading@11 580 }
yading@11 581 while (pos_min <= pos_max) {
yading@11 582 pts_min = get_dts(s, pos_min);
yading@11 583 pts_max = get_dts(s, pos_max);
yading@11 584 if (pts_min > wanted_pts || pts_max <= wanted_pts) {
yading@11 585 pos = pts_min > wanted_pts ? pos_min : pos_max;
yading@11 586 goto found;
yading@11 587 }
yading@11 588 /* linear interpolation */
yading@11 589 pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
yading@11 590 (double)(pts_max - pts_min);
yading@11 591 pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
yading@11 592 if (pos <= pos_min)
yading@11 593 pos = pos_min;
yading@11 594 else if (pos >= pos_max)
yading@11 595 pos = pos_max;
yading@11 596 pts = get_dts(s, pos);
yading@11 597 /* check if we are lucky */
yading@11 598 if (pts == wanted_pts) {
yading@11 599 goto found;
yading@11 600 } else if (pts > wanted_pts) {
yading@11 601 pos_max = pos - FFM_PACKET_SIZE;
yading@11 602 } else {
yading@11 603 pos_min = pos + FFM_PACKET_SIZE;
yading@11 604 }
yading@11 605 }
yading@11 606 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
yading@11 607
yading@11 608 found:
yading@11 609 if (ffm_seek1(s, pos) < 0)
yading@11 610 return -1;
yading@11 611
yading@11 612 /* reset read state */
yading@11 613 ffm->read_state = READ_HEADER;
yading@11 614 ffm->packet_ptr = ffm->packet;
yading@11 615 ffm->packet_end = ffm->packet;
yading@11 616 ffm->first_packet = 1;
yading@11 617
yading@11 618 return 0;
yading@11 619 }
yading@11 620
yading@11 621 static int ffm_probe(AVProbeData *p)
yading@11 622 {
yading@11 623 if (
yading@11 624 p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
yading@11 625 (p->buf[3] == '1' || p->buf[3] == '2'))
yading@11 626 return AVPROBE_SCORE_MAX + 1;
yading@11 627 return 0;
yading@11 628 }
yading@11 629
yading@11 630 AVInputFormat ff_ffm_demuxer = {
yading@11 631 .name = "ffm",
yading@11 632 .long_name = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed)"),
yading@11 633 .priv_data_size = sizeof(FFMContext),
yading@11 634 .read_probe = ffm_probe,
yading@11 635 .read_header = ffm_read_header,
yading@11 636 .read_packet = ffm_read_packet,
yading@11 637 .read_close = ffm_close,
yading@11 638 .read_seek = ffm_seek,
yading@11 639 };