Remove avserver.

It has not been properly maintained for years and there is little hope
of that changing in the future.
It appears simpler to write a new replacement from scratch than
unbreaking it.
pull/76/merge
Anton Khirnov 11 years ago
parent f2ce63246f
commit 894682a973
  1. 1
      .gitignore
  2. 1
      Changelog
  3. 3
      Makefile
  4. 4685
      avserver.c
  5. 10
      configure
  6. 372
      doc/avserver.conf
  7. 276
      doc/avserver.texi
  8. 1
      doc/general.texi
  9. 2
      libavformat/Makefile
  10. 1
      libavformat/allformats.c
  11. 59
      libavformat/ffm.h
  12. 483
      libavformat/ffmdec.c
  13. 249
      libavformat/ffmenc.c
  14. 1
      tests/fate/avformat.mak
  15. 2
      tests/fate/seek.mak
  16. 4
      tests/lavf-regression.sh
  17. 3
      tests/ref/lavf/ffm
  18. 53
      tests/ref/seek/lavf-ffm

1
.gitignore vendored

@ -24,7 +24,6 @@
/avconv /avconv
/avplay /avplay
/avprobe /avprobe
/avserver
/config.* /config.*
/coverage.info /coverage.info
/version.h /version.h

@ -27,6 +27,7 @@ version <next>:
- libbs2b-based stereo-to-binaural audio filter - libbs2b-based stereo-to-binaural audio filter
- native Opus decoder - native Opus decoder
- display matrix export and rotation api - display matrix export and rotation api
- drop avserver, it was unmaintained for years and largely broken
version 10: version 10:

@ -63,12 +63,11 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC)
AVPROGS-$(CONFIG_AVCONV) += avconv AVPROGS-$(CONFIG_AVCONV) += avconv
AVPROGS-$(CONFIG_AVPLAY) += avplay AVPROGS-$(CONFIG_AVPLAY) += avplay
AVPROGS-$(CONFIG_AVPROBE) += avprobe AVPROGS-$(CONFIG_AVPROBE) += avprobe
AVPROGS-$(CONFIG_AVSERVER) += avserver
AVPROGS := $(AVPROGS-yes:%=%$(EXESUF)) AVPROGS := $(AVPROGS-yes:%=%$(EXESUF))
PROGS += $(AVPROGS) PROGS += $(AVPROGS)
AVBASENAMES = avconv avplay avprobe avserver AVBASENAMES = avconv avplay avprobe
ALLAVPROGS = $(AVBASENAMES:%=%$(EXESUF)) ALLAVPROGS = $(AVBASENAMES:%=%$(EXESUF))
$(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o)) $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o))

File diff suppressed because it is too large Load Diff

10
configure vendored

@ -108,7 +108,7 @@ Program options:
--disable-avconv disable avconv build --disable-avconv disable avconv build
--disable-avplay disable avplay build --disable-avplay disable avplay build
--disable-avprobe disable avprobe build --disable-avprobe disable avprobe build
--disable-avserver disable avserver build --disable-avserver deprecated, does nothing
Component options: Component options:
--disable-doc do not build documentation --disable-doc do not build documentation
@ -1209,7 +1209,6 @@ PROGRAM_LIST="
avconv avconv
avplay avplay
avprobe avprobe
avserver
" "
SUBSYSTEM_LIST=" SUBSYSTEM_LIST="
@ -2142,8 +2141,6 @@ avplay_deps="avcodec avformat avresample swscale sdl"
avplay_libs='$sdl_libs' avplay_libs='$sdl_libs'
avplay_select="rdft" avplay_select="rdft"
avprobe_deps="avcodec avformat" avprobe_deps="avcodec avformat"
avserver_deps="avformat fork !shared"
avserver_select="ffm_muxer rtp_protocol rtsp_demuxer"
# documentation # documentation
pod2man_deps="doc" pod2man_deps="doc"
@ -2380,6 +2377,10 @@ for opt do
name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing} name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing}
$action $(filter "$name" $list) $action $(filter "$name" $list)
;; ;;
--enable-avserver|--disable-avserver*)
warn "avserver has been removed, the ${opt} option is only"\
"provided for compatibility and will be removed in the future"
;;
--enable-?*|--disable-?*) --enable-?*|--disable-?*)
eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g') eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g')
if is_in $option $COMPONENT_LIST; then if is_in $option $COMPONENT_LIST; then
@ -3539,7 +3540,6 @@ case $target_os in
add_compat strtod.o strtod=avpriv_strtod add_compat strtod.o strtod=avpriv_strtod
network_extralibs='-lbsd' network_extralibs='-lbsd'
exeobjs=compat/plan9/main.o exeobjs=compat/plan9/main.o
disable avserver
cp_f='cp' cp_f='cp'
;; ;;
none) none)

@ -1,372 +0,0 @@
# Port on which the server is listening. You must select a different
# port from your standard HTTP web server if it is running on the same
# computer.
Port 8090
# Address on which the server is bound. Only useful if you have
# several network interfaces.
BindAddress 0.0.0.0
# Number of simultaneous HTTP connections that can be handled. It has
# to be defined *before* the MaxClients parameter, since it defines the
# MaxClients maximum limit.
MaxHTTPConnections 2000
# Number of simultaneous requests that can be handled. Since AVServer
# is very fast, it is more likely that you will want to leave this high
# and use MaxBandwidth, below.
MaxClients 1000
# This the maximum amount of kbit/sec that you are prepared to
# consume when streaming to clients.
MaxBandwidth 1000
# Access log file (uses standard Apache log file format)
# '-' is the standard output.
CustomLog -
##################################################################
# Definition of the live feeds. Each live feed contains one video
# and/or audio sequence coming from an avconv encoder or another
# avserver. This sequence may be encoded simultaneously with several
# codecs at several resolutions.
<Feed feed1.ffm>
# You must use 'avconv' to send a live feed to avserver. In this
# example, you can type:
#
# avconv http://localhost:8090/feed1.ffm
# avserver can also do time shifting. It means that it can stream any
# previously recorded live stream. The request should contain:
# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify
# a path where the feed is stored on disk. You also specify the
# maximum size of the feed, where zero means unlimited. Default:
# File=/tmp/feed_name.ffm FileMaxSize=5M
File /tmp/feed1.ffm
FileMaxSize 200K
# You could specify
# ReadOnlyFile /saved/specialvideo.ffm
# This marks the file as readonly and it will not be deleted or updated.
# Specify launch in order to start avconv automatically.
# First avconv must be defined with an appropriate path if needed,
# after that options can follow, but avoid adding the http:// field
#Launch avconv
# Only allow connections from localhost to the feed.
ACL allow 127.0.0.1
</Feed>
##################################################################
# Now you can define each stream which will be generated from the
# original audio and video stream. Each format has a filename (here
# 'test1.mpg'). AVServer will send this stream when answering a
# request containing this filename.
<Stream test1.mpg>
# coming from live feed 'feed1'
Feed feed1.ffm
# Format of the stream : you can choose among:
# mpeg : MPEG-1 multiplexed video and audio
# mpegvideo : only MPEG-1 video
# mp2 : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec)
# ogg : Ogg format (Vorbis audio codec)
# rm : RealNetworks-compatible stream. Multiplexed audio and video.
# ra : RealNetworks-compatible stream. Audio only.
# mpjpeg : Multipart JPEG (works with Netscape without any plugin)
# jpeg : Generate a single JPEG image.
# asf : ASF compatible streaming (Windows Media Player format).
# swf : Macromedia Flash compatible stream
# avi : AVI format (MPEG-4 video, MPEG audio sound)
Format mpeg
# Bitrate for the audio stream. Codecs usually support only a few
# different bitrates.
AudioBitRate 32
# Number of audio channels: 1 = mono, 2 = stereo
AudioChannels 1
# Sampling frequency for audio. When using low bitrates, you should
# lower this frequency to 22050 or 11025. The supported frequencies
# depend on the selected audio codec.
AudioSampleRate 44100
# Bitrate for the video stream
VideoBitRate 64
# Ratecontrol buffer size
VideoBufferSize 40
# Number of frames per second
VideoFrameRate 3
# Size of the video frame: WxH (default: 160x128)
# The following abbreviations are defined: sqcif, qcif, cif, 4cif, qqvga,
# qvga, vga, svga, xga, uxga, qxga, sxga, qsxga, hsxga, wvga, wxga, wsxga,
# wuxga, woxga, wqsxga, wquxga, whsxga, whuxga, cga, ega, hd480, hd720,
# hd1080
VideoSize 160x128
# Transmit only intra frames (useful for low bitrates, but kills frame rate).
#VideoIntraOnly
# If non-intra only, an intra frame is transmitted every VideoGopSize
# frames. Video synchronization can only begin at an intra frame.
VideoGopSize 12
# More MPEG-4 parameters
# VideoHighQuality
# Video4MotionVector
# Choose your codecs:
#AudioCodec mp2
#VideoCodec mpeg1video
# Suppress audio
#NoAudio
# Suppress video
#NoVideo
#VideoQMin 3
#VideoQMax 31
# Set this to the number of seconds backwards in time to start. Note that
# most players will buffer 5-10 seconds of video, and also you need to allow
# for a keyframe to appear in the data stream.
#Preroll 15
# ACL:
# You can allow ranges of addresses (or single addresses)
#ACL ALLOW <first address> <last address>
# You can deny ranges of addresses (or single addresses)
#ACL DENY <first address> <last address>
# You can repeat the ACL allow/deny as often as you like. It is on a per
# stream basis. The first match defines the action. If there are no matches,
# then the default is the inverse of the last ACL statement.
#
# Thus 'ACL allow localhost' only allows access from localhost.
# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
# allow everybody else.
</Stream>
##################################################################
# Example streams
# Multipart JPEG
#<Stream test.mjpg>
#Feed feed1.ffm
#Format mpjpeg
#VideoFrameRate 2
#VideoIntraOnly
#NoAudio
#Strict -1
#</Stream>
# Single JPEG
#<Stream test.jpg>
#Feed feed1.ffm
#Format jpeg
#VideoFrameRate 2
#VideoIntraOnly
##VideoSize 352x240
#NoAudio
#Strict -1
#</Stream>
# Flash
#<Stream test.swf>
#Feed feed1.ffm
#Format swf
#VideoFrameRate 2
#VideoIntraOnly
#NoAudio
#</Stream>
# ASF compatible
<Stream test.asf>
Feed feed1.ffm
Format asf
VideoFrameRate 15
VideoSize 352x240
VideoBitRate 256
VideoBufferSize 40
VideoGopSize 30
AudioBitRate 64
StartSendOnKey
</Stream>
# MP3 audio
#<Stream test.mp3>
#Feed feed1.ffm
#Format mp2
#AudioCodec mp3
#AudioBitRate 64
#AudioChannels 1
#AudioSampleRate 44100
#NoVideo
#</Stream>
# Ogg Vorbis audio
#<Stream test.ogg>
#Feed feed1.ffm
#Title "Stream title"
#AudioBitRate 64
#AudioChannels 2
#AudioSampleRate 44100
#NoVideo
#</Stream>
# Real with audio only at 32 kbits
#<Stream test.ra>
#Feed feed1.ffm
#Format rm
#AudioBitRate 32
#NoVideo
#NoAudio
#</Stream>
# Real with audio and video at 64 kbits
#<Stream test.rm>
#Feed feed1.ffm
#Format rm
#AudioBitRate 32
#VideoBitRate 128
#VideoFrameRate 25
#VideoGopSize 25
#NoAudio
#</Stream>
##################################################################
# A stream coming from a file: you only need to set the input
# filename and optionally a new format. Supported conversions:
# AVI -> ASF
#<Stream file.rm>
#File "/usr/local/httpd/htdocs/tlive.rm"
#NoAudio
#</Stream>
#<Stream file.asf>
#File "/usr/local/httpd/htdocs/test.asf"
#NoAudio
#Author "Me"
#Copyright "Super MegaCorp"
#Title "Test stream from disk"
#Comment "Test comment"
#</Stream>
##################################################################
# RTSP examples
#
# You can access this stream with the RTSP URL:
# rtsp://localhost:5454/test1-rtsp.mpg
#
# A non-standard RTSP redirector is also created. Its URL is:
# http://localhost:8090/test1-rtsp.rtsp
#<Stream test1-rtsp.mpg>
#Format rtp
#File "/usr/local/httpd/htdocs/test1.mpg"
#</Stream>
# Transcode an incoming live feed to another live feed,
# using libx264 and video presets
#<Stream live.h264>
#Format rtp
#Feed feed1.ffm
#VideoCodec libx264
#VideoFrameRate 24
#VideoBitRate 100
#VideoSize 480x272
#AVPresetVideo default
#AVPresetVideo baseline
#AVOptionVideo flags +global_header
#
#AudioCodec libfaac
#AudioBitRate 32
#AudioChannels 2
#AudioSampleRate 22050
#AVOptionAudio flags +global_header
#</Stream>
##################################################################
# SDP/multicast examples
#
# If you want to send your stream in multicast, you must set the
# multicast address with MulticastAddress. The port and the TTL can
# also be set.
#
# An SDP file is automatically generated by avserver by adding the
# 'sdp' extension to the stream name (here
# http://localhost:8090/test1-sdp.sdp). You should usually give this
# file to your player to play the stream.
#
# The 'NoLoop' option can be used to avoid looping when the stream is
# terminated.
#<Stream test1-sdp.mpg>
#Format rtp
#File "/usr/local/httpd/htdocs/test1.mpg"
#MulticastAddress 224.124.0.1
#MulticastPort 5000
#MulticastTTL 16
#NoLoop
#</Stream>
##################################################################
# Special streams
# Server status
<Stream stat.html>
Format status
# Only allow local people to get the status
ACL allow localhost
ACL allow 192.168.0.0 192.168.255.255
#FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico
</Stream>
# Redirect index.html to the appropriate site
<Redirect index.html>
URL http://www.libav.org/
</Redirect>

@ -1,276 +0,0 @@
\input texinfo @c -*- texinfo -*-
@settitle avserver Documentation
@titlepage
@center @titlefont{avserver Documentation}
@end titlepage
@top
@contents
@chapter Synopsys
The generic syntax is:
@example
@c man begin SYNOPSIS
avserver [options]
@c man end
@end example
@chapter Description
@c man begin DESCRIPTION
WARNING: avserver is unmaintained, largely broken and in need of a
complete rewrite. It probably won't work for you. Use at your own
risk.
avserver is a streaming server for both audio and video. It supports
several live feeds, streaming from files and time shifting on live feeds
(you can seek to positions in the past on each live feed, provided you
specify a big enough feed storage in avserver.conf).
This documentation covers only the streaming aspects of avserver /
avconv. All questions about parameters for avconv, codec questions,
etc. are not covered here. Read @file{avconv.html} for more
information.
@section How does it work?
avserver receives prerecorded files or FFM streams from some avconv
instance as input, then streams them over RTP/RTSP/HTTP.
An avserver instance will listen on some port as specified in the
configuration file. You can launch one or more instances of avconv and
send one or more FFM streams to the port where avserver is expecting
to receive them. Alternately, you can make avserver launch such avconv
instances at startup.
Input streams are called feeds, and each one is specified by a <Feed>
section in the configuration file.
For each feed you can have different output streams in various
formats, each one specified by a <Stream> section in the configuration
file.
@section Status stream
avserver supports an HTTP interface which exposes the current status
of the server.
Simply point your browser to the address of the special status stream
specified in the configuration file.
For example if you have:
@example
<Stream status.html>
Format status
# Only allow local people to get the status
ACL allow localhost
ACL allow 192.168.0.0 192.168.255.255
</Stream>
@end example
then the server will post a page with the status information when
the special stream @file{status.html} is requested.
@section What can this do?
When properly configured and running, you can capture video and audio in real
time from a suitable capture card, and stream it out over the Internet to
either Windows Media Player or RealAudio player (with some restrictions).
It can also stream from files, though that is currently broken. Very often, a
web server can be used to serve up the files just as well.
It can stream prerecorded video from .ffm files, though it is somewhat tricky
to make it work correctly.
@section What do I need?
I use Linux on a 900 MHz Duron with a cheapo Bt848 based TV capture card. I'm
using stock Linux 2.4.17 with the stock drivers. [Actually that isn't true,
I needed some special drivers for my motherboard-based sound card.]
I understand that FreeBSD systems work just fine as well.
@section How do I make it work?
First, build the kit. It *really* helps to have installed LAME first. Then when
you run the avserver ./configure, make sure that you have the
@code{--enable-libmp3lame} flag turned on.
LAME is important as it allows for streaming audio to Windows Media Player.
Don't ask why the other audio types do not work.
As a simple test, just run the following two command lines where INPUTFILE
is some file which you can decode with avconv:
@example
./avserver -f doc/avserver.conf &
./avconv -i INPUTFILE http://localhost:8090/feed1.ffm
@end example
At this point you should be able to go to your Windows machine and fire up
Windows Media Player (WMP). Go to Open URL and enter
@example
http://<linuxbox>:8090/test.asf
@end example
You should (after a short delay) see video and hear audio.
WARNING: trying to stream test1.mpg doesn't work with WMP as it tries to
transfer the entire file before starting to play.
The same is true of AVI files.
@section What happens next?
You should edit the avserver.conf file to suit your needs (in terms of
frame rates etc). Then install avserver and avconv, write a script to start
them up, and off you go.
@section Troubleshooting
@subsection I don't hear any audio, but video is fine.
Maybe you didn't install LAME, or got your ./configure statement wrong. Check
the avconv output to see if a line referring to MP3 is present. If not, then
your configuration was incorrect. If it is, then maybe your wiring is not
set up correctly. Maybe the sound card is not getting data from the right
input source. Maybe you have a really awful audio interface (like I do)
that only captures in stereo and also requires that one channel be flipped.
If you are one of these people, then export 'AUDIO_FLIP_LEFT=1' before
starting avconv.
@subsection The audio and video lose sync after a while.
Yes, they do.
@subsection After a long while, the video update rate goes way down in WMP.
Yes, it does. Who knows why?
@subsection WMP 6.4 behaves differently to WMP 7.
Yes, it does. Any thoughts on this would be gratefully received. These
differences extend to embedding WMP into a web page. [There are two
object IDs that you can use: The old one, which does not play well, and
the new one, which does (both tested on the same system). However,
I suspect that the new one is not available unless you have installed WMP 7].
@section What else can it do?
You can replay video from .ffm files that was recorded earlier.
However, there are a number of caveats, including the fact that the
avserver parameters must match the original parameters used to record the
file. If they do not, then avserver deletes the file before recording into it.
(Now that I write this, it seems broken).
You can fiddle with many of the codec choices and encoding parameters, and
there are a bunch more parameters that you cannot control. Post a message
to the mailing list if there are some 'must have' parameters. Look in
avserver.conf for a list of the currently available controls.
It will automatically generate the ASX or RAM files that are often used
in browsers. These files are actually redirections to the underlying ASF
or RM file. The reason for this is that the browser often fetches the
entire file before starting up the external viewer. The redirection files
are very small and can be transferred quickly. [The stream itself is
often 'infinite' and thus the browser tries to download it and never
finishes.]
@section Tips
* When you connect to a live stream, most players (WMP, RA, etc) want to
buffer a certain number of seconds of material so that they can display the
signal continuously. However, avserver (by default) starts sending data
in realtime. This means that there is a pause of a few seconds while the
buffering is being done by the player. The good news is that this can be
cured by adding a '?buffer=5' to the end of the URL. This means that the
stream should start 5 seconds in the past -- and so the first 5 seconds
of the stream are sent as fast as the network will allow. It will then
slow down to real time. This noticeably improves the startup experience.
You can also add a 'Preroll 15' statement into the avserver.conf that will
add the 15 second prebuffering on all requests that do not otherwise
specify a time. In addition, avserver will skip frames until a key_frame
is found. This further reduces the startup delay by not transferring data
that will be discarded.
* You may want to adjust the MaxBandwidth in the avserver.conf to limit
the amount of bandwidth consumed by live streams.
@section Why does the ?buffer / Preroll stop working after a time?
It turns out that (on my machine at least) the number of frames successfully
grabbed is marginally less than the number that ought to be grabbed. This
means that the timestamp in the encoded data stream gets behind realtime.
This means that if you say 'Preroll 10', then when the stream gets 10
or more seconds behind, there is no Preroll left.
Fixing this requires a change in the internals of how timestamps are
handled.
@section Does the @code{?date=} stuff work.
Yes (subject to the limitation outlined above). Also note that whenever you
start avserver, it deletes the ffm file (if any parameters have changed),
thus wiping out what you had recorded before.
The format of the @code{?date=xxxxxx} is fairly flexible. You should use one
of the following formats (the 'T' is literal):
@example
* YYYY-MM-DDTHH:MM:SS (localtime)
* YYYY-MM-DDTHH:MM:SSZ (UTC)
@end example
You can omit the YYYY-MM-DD, and then it refers to the current day. However
note that @samp{?date=16:00:00} refers to 16:00 on the current day -- this
may be in the future and so is unlikely to be useful.
You use this by adding the ?date= to the end of the URL for the stream.
For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}.
@c man end
@chapter Options
@c man begin OPTIONS
@include avtools-common-opts.texi
@section Main options
@table @option
@item -f @var{configfile}
Use @file{configfile} instead of @file{/etc/avserver.conf}.
@item -n
Enable no-launch mode. This option disables all the Launch directives
within the various <Stream> sections. Since avserver will not launch
any avconv instances, you will have to launch them manually.
@item -d
Enable debug mode. This option increases log verbosity, directs log
messages to stdout.
@end table
@c man end
@ignore
@setfilename avserver
@settitle avserver video server
@c man begin SEEALSO
avconv(1), avplay(1), avprobe(1), the @file{avserver.conf}
example and the Libav HTML documentation
@c man end
@c man begin AUTHORS
The Libav developers
@c man end
@end ignore
@bye

@ -235,7 +235,6 @@ library:
@item Electronic Arts cdata @tab @tab X @item Electronic Arts cdata @tab @tab X
@item Electronic Arts Multimedia @tab @tab X @item Electronic Arts Multimedia @tab @tab X
@tab Used in various EA games; files have extensions like WVE and UV2. @tab Used in various EA games; files have extensions like WVE and UV2.
@item FFM (AVserver live feed) @tab X @tab X
@item Flash (SWF) @tab X @tab X @item Flash (SWF) @tab X @tab X
@item Flash 9 (AVM2) @tab X @tab X @item Flash 9 (AVM2) @tab X @tab X
@tab Only embedded audio is decoded. @tab Only embedded audio is decoded.

@ -107,8 +107,6 @@ OBJS-$(CONFIG_EA_CDATA_DEMUXER) += eacdata.o
OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o
OBJS-$(CONFIG_EAC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_EAC3_DEMUXER) += ac3dec.o rawdec.o
OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o
OBJS-$(CONFIG_FFM_DEMUXER) += ffmdec.o
OBJS-$(CONFIG_FFM_MUXER) += ffmenc.o
OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o
OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o
OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o

@ -100,7 +100,6 @@ void av_register_all(void)
REGISTER_DEMUXER (EA_CDATA, ea_cdata); REGISTER_DEMUXER (EA_CDATA, ea_cdata);
REGISTER_MUXDEMUX(EAC3, eac3); REGISTER_MUXDEMUX(EAC3, eac3);
REGISTER_MUXER (F4V, f4v); REGISTER_MUXER (F4V, f4v);
REGISTER_MUXDEMUX(FFM, ffm);
REGISTER_MUXDEMUX(FFMETADATA, ffmetadata); REGISTER_MUXDEMUX(FFMETADATA, ffmetadata);
REGISTER_MUXDEMUX(FILMSTRIP, filmstrip); REGISTER_MUXDEMUX(FILMSTRIP, filmstrip);
REGISTER_MUXDEMUX(FLAC, flac); REGISTER_MUXDEMUX(FLAC, flac);

@ -1,59 +0,0 @@
/*
* FFM (avserver live feed) common header
* Copyright (c) 2001 Fabrice Bellard
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_FFM_H
#define AVFORMAT_FFM_H
#include <stdint.h>
#include "avformat.h"
#include "avio.h"
/* The FFM file is made of blocks of fixed size */
#define FFM_HEADER_SIZE 14
#define FFM_PACKET_SIZE 4096
#define PACKET_ID 0x666d
/* each packet contains frames (which can span several packets */
#define FRAME_HEADER_SIZE 16
#define FLAG_KEY_FRAME 0x01
#define FLAG_DTS 0x02
enum {
READ_HEADER,
READ_DATA,
};
typedef struct FFMContext {
/* only reading mode */
int64_t write_index, file_size;
int read_state;
uint8_t header[FRAME_HEADER_SIZE+4];
/* read and write */
int first_packet; /* true if first packet, needed to set the discontinuity tag */
int packet_size;
int frame_offset;
int64_t dts;
uint8_t *packet_ptr, *packet_end;
uint8_t packet[FFM_PACKET_SIZE];
} FFMContext;
#endif /* AVFORMAT_FFM_H */

@ -1,483 +0,0 @@
/*
* FFM (avserver live feed) demuxer
* Copyright (c) 2001 Fabrice Bellard
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "avformat.h"
#include "internal.h"
#include "ffm.h"
static int ffm_is_avail_data(AVFormatContext *s, int size)
{
FFMContext *ffm = s->priv_data;
int64_t pos, avail_size;
int len;
len = ffm->packet_end - ffm->packet_ptr;
if (size <= len)
return 1;
pos = avio_tell(s->pb);
if (!ffm->write_index) {
if (pos == ffm->file_size)
return AVERROR_EOF;
avail_size = ffm->file_size - pos;
} else {
if (pos == ffm->write_index) {
/* exactly at the end of stream */
return AVERROR(EAGAIN);
} else if (pos < ffm->write_index) {
avail_size = ffm->write_index - pos;
} else {
avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
}
}
avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
if (size <= avail_size)
return 1;
else
return AVERROR(EAGAIN);
}
static int ffm_resync(AVFormatContext *s, int state)
{
av_log(s, AV_LOG_ERROR, "resyncing\n");
while (state != PACKET_ID) {
if (s->pb->eof_reached) {
av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n");
return -1;
}
state = (state << 8) | avio_r8(s->pb);
}
return 0;
}
/* first is true if we read the frame header */
static int ffm_read_data(AVFormatContext *s,
uint8_t *buf, int size, int header)
{
FFMContext *ffm = s->priv_data;
AVIOContext *pb = s->pb;
int len, fill_size, size1, frame_offset, id;
size1 = size;
while (size > 0) {
redo:
len = ffm->packet_end - ffm->packet_ptr;
if (len < 0)
return -1;
if (len > size)
len = size;
if (len == 0) {
if (avio_tell(pb) == ffm->file_size)
avio_seek(pb, ffm->packet_size, SEEK_SET);
retry_read:
id = avio_rb16(pb); /* PACKET_ID */
if (id != PACKET_ID)
if (ffm_resync(s, id) < 0)
return -1;
fill_size = avio_rb16(pb);
ffm->dts = avio_rb64(pb);
frame_offset = avio_rb16(pb);
avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
if (ffm->packet_end < ffm->packet || frame_offset < 0)
return -1;
/* if first packet or resynchronization packet, we must
handle it specifically */
if (ffm->first_packet || (frame_offset & 0x8000)) {
if (!frame_offset) {
/* This packet has no frame headers in it */
if (avio_tell(pb) >= ffm->packet_size * 3) {
avio_seek(pb, -ffm->packet_size * 2, SEEK_CUR);
goto retry_read;
}
/* This is bad, we cannot find a valid frame header */
return 0;
}
ffm->first_packet = 0;
if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE)
return -1;
ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
if (!header)
break;
} else {
ffm->packet_ptr = ffm->packet;
}
goto redo;
}
memcpy(buf, ffm->packet_ptr, len);
buf += len;
ffm->packet_ptr += len;
size -= len;
header = 0;
}
return size1 - size;
}
/* ensure that acutal seeking happens between FFM_PACKET_SIZE
and file_size - FFM_PACKET_SIZE */
static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1)
{
FFMContext *ffm = s->priv_data;
AVIOContext *pb = s->pb;
int64_t pos;
pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE);
pos = FFMAX(pos, FFM_PACKET_SIZE);
av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
return avio_seek(pb, pos, SEEK_SET);
}
static int64_t get_dts(AVFormatContext *s, int64_t pos)
{
AVIOContext *pb = s->pb;
int64_t dts;
ffm_seek1(s, pos);
avio_skip(pb, 4);
dts = avio_rb64(pb);
av_dlog(s, "dts=%0.6f\n", dts / 1000000.0);
return dts;
}
static void adjust_write_index(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
AVIOContext *pb = s->pb;
int64_t pts;
//int64_t orig_write_index = ffm->write_index;
int64_t pos_min, pos_max;
int64_t pts_start;
int64_t ptr = avio_tell(pb);
pos_min = 0;
pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
pts_start = get_dts(s, pos_min);
pts = get_dts(s, pos_max);
if (pts - 100000 > pts_start)
goto end;
ffm->write_index = FFM_PACKET_SIZE;
pts_start = get_dts(s, pos_min);
pts = get_dts(s, pos_max);
if (pts - 100000 <= pts_start) {
while (1) {
int64_t newpos;
int64_t newpts;
newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
if (newpos == pos_min)
break;
newpts = get_dts(s, newpos);
if (newpts - 100000 <= pts) {
pos_max = newpos;
pts = newpts;
} else {
pos_min = newpos;
}
}
ffm->write_index += pos_max;
}
end:
avio_seek(pb, ptr, SEEK_SET);
}
static int ffm_close(AVFormatContext *s)
{
int i;
for (i = 0; i < s->nb_streams; i++)
av_freep(&s->streams[i]->codec->rc_eq);
return 0;
}
static int ffm_read_header(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
AVStream *st;
AVIOContext *pb = s->pb;
AVCodecContext *codec;
int i, nb_streams;
uint32_t tag;
/* header */
tag = avio_rl32(pb);
if (tag != MKTAG('F', 'F', 'M', '1'))
goto fail;
ffm->packet_size = avio_rb32(pb);
if (ffm->packet_size != FFM_PACKET_SIZE)
goto fail;
ffm->write_index = avio_rb64(pb);
/* get also filesize */
if (pb->seekable) {
ffm->file_size = avio_size(pb);
if (ffm->write_index)
adjust_write_index(s);
} else {
ffm->file_size = (UINT64_C(1) << 63) - 1;
}
nb_streams = avio_rb32(pb);
avio_rb32(pb); /* total bitrate */
/* read each stream */
for(i=0;i<nb_streams;i++) {
char rc_eq_buf[128];
st = avformat_new_stream(s, NULL);
if (!st)
goto fail;
avpriv_set_pts_info(st, 64, 1, 1000000);
codec = st->codec;
/* generic info */
codec->codec_id = avio_rb32(pb);
codec->codec_type = avio_r8(pb); /* codec_type */
codec->bit_rate = avio_rb32(pb);
codec->flags = avio_rb32(pb);
codec->flags2 = avio_rb32(pb);
codec->debug = avio_rb32(pb);
/* specific info */
switch(codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
codec->time_base.num = avio_rb32(pb);
codec->time_base.den = avio_rb32(pb);
codec->width = avio_rb16(pb);
codec->height = avio_rb16(pb);
codec->gop_size = avio_rb16(pb);
codec->pix_fmt = avio_rb32(pb);
codec->qmin = avio_r8(pb);
codec->qmax = avio_r8(pb);
codec->max_qdiff = avio_r8(pb);
codec->qcompress = avio_rb16(pb) / 10000.0;
codec->qblur = avio_rb16(pb) / 10000.0;
codec->bit_rate_tolerance = avio_rb32(pb);
avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
codec->rc_eq = av_strdup(rc_eq_buf);
codec->rc_max_rate = avio_rb32(pb);
codec->rc_min_rate = avio_rb32(pb);
codec->rc_buffer_size = avio_rb32(pb);
codec->i_quant_factor = av_int2double(avio_rb64(pb));
codec->b_quant_factor = av_int2double(avio_rb64(pb));
codec->i_quant_offset = av_int2double(avio_rb64(pb));
codec->b_quant_offset = av_int2double(avio_rb64(pb));
codec->dct_algo = avio_rb32(pb);
codec->strict_std_compliance = avio_rb32(pb);
codec->max_b_frames = avio_rb32(pb);
codec->mpeg_quant = avio_rb32(pb);
codec->intra_dc_precision = avio_rb32(pb);
codec->me_method = avio_rb32(pb);
codec->mb_decision = avio_rb32(pb);
codec->nsse_weight = avio_rb32(pb);
codec->frame_skip_cmp = avio_rb32(pb);
codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
codec->codec_tag = avio_rb32(pb);
codec->thread_count = avio_r8(pb);
codec->coder_type = avio_rb32(pb);
codec->me_cmp = avio_rb32(pb);
codec->me_subpel_quality = avio_rb32(pb);
codec->me_range = avio_rb32(pb);
codec->keyint_min = avio_rb32(pb);
codec->scenechange_threshold = avio_rb32(pb);
codec->b_frame_strategy = avio_rb32(pb);
codec->qcompress = av_int2double(avio_rb64(pb));
codec->qblur = av_int2double(avio_rb64(pb));
codec->max_qdiff = avio_rb32(pb);
codec->refs = avio_rb32(pb);
break;
case AVMEDIA_TYPE_AUDIO:
codec->sample_rate = avio_rb32(pb);
codec->channels = avio_rl16(pb);
codec->frame_size = avio_rl16(pb);
break;
default:
goto fail;
}
if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
codec->extradata_size = avio_rb32(pb);
codec->extradata = av_malloc(codec->extradata_size);
if (!codec->extradata)
return AVERROR(ENOMEM);
avio_read(pb, codec->extradata, codec->extradata_size);
}
}
/* get until end of block reached */
while ((avio_tell(pb) % ffm->packet_size) != 0)
avio_r8(pb);
/* init packet demux */
ffm->packet_ptr = ffm->packet;
ffm->packet_end = ffm->packet;
ffm->frame_offset = 0;
ffm->dts = 0;
ffm->read_state = READ_HEADER;
ffm->first_packet = 1;
return 0;
fail:
ffm_close(s);
return -1;
}
/* return < 0 if eof */
static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int size;
FFMContext *ffm = s->priv_data;
int duration, ret;
switch(ffm->read_state) {
case READ_HEADER:
if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0)
return ret;
av_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size);
if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
FRAME_HEADER_SIZE)
return -1;
if (ffm->header[1] & FLAG_DTS)
if (ffm_read_data(s, ffm->header+16, 4, 1) != 4)
return -1;
ffm->read_state = READ_DATA;
/* fall thru */
case READ_DATA:
size = AV_RB24(ffm->header + 2);
if ((ret = ffm_is_avail_data(s, size)) < 0)
return ret;
duration = AV_RB24(ffm->header + 5);
av_new_packet(pkt, size);
pkt->stream_index = ffm->header[0];
if ((unsigned)pkt->stream_index >= s->nb_streams) {
av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index);
av_free_packet(pkt);
ffm->read_state = READ_HEADER;
return -1;
}
pkt->pos = avio_tell(s->pb);
if (ffm->header[1] & FLAG_KEY_FRAME)
pkt->flags |= AV_PKT_FLAG_KEY;
ffm->read_state = READ_HEADER;
if (ffm_read_data(s, pkt->data, size, 0) != size) {
/* bad case: desynchronized packet. we cancel all the packet loading */
av_free_packet(pkt);
return -1;
}
pkt->pts = AV_RB64(ffm->header+8);
if (ffm->header[1] & FLAG_DTS)
pkt->dts = pkt->pts - AV_RB32(ffm->header+16);
else
pkt->dts = pkt->pts;
pkt->duration = duration;
break;
}
return 0;
}
/* seek to a given time in the file. The file read pointer is
positioned at or before pts. XXX: the following code is quite
approximative */
static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
{
FFMContext *ffm = s->priv_data;
int64_t pos_min, pos_max, pos;
int64_t pts_min, pts_max, pts;
double pos1;
av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
/* find the position using linear interpolation (better than
dichotomy in typical cases) */
pos_min = FFM_PACKET_SIZE;
pos_max = ffm->file_size - FFM_PACKET_SIZE;
while (pos_min <= pos_max) {
pts_min = get_dts(s, pos_min);
pts_max = get_dts(s, pos_max);
/* linear interpolation */
pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
(double)(pts_max - pts_min);
pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
if (pos <= pos_min)
pos = pos_min;
else if (pos >= pos_max)
pos = pos_max;
pts = get_dts(s, pos);
/* check if we are lucky */
if (pts == wanted_pts) {
goto found;
} else if (pts > wanted_pts) {
pos_max = pos - FFM_PACKET_SIZE;
} else {
pos_min = pos + FFM_PACKET_SIZE;
}
}
pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
found:
if (ffm_seek1(s, pos) < 0)
return -1;
/* reset read state */
ffm->read_state = READ_HEADER;
ffm->packet_ptr = ffm->packet;
ffm->packet_end = ffm->packet;
ffm->first_packet = 1;
return 0;
}
static int ffm_probe(AVProbeData *p)
{
if (
p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
p->buf[3] == '1')
return AVPROBE_SCORE_MAX + 1;
return 0;
}
AVInputFormat ff_ffm_demuxer = {
.name = "ffm",
.long_name = NULL_IF_CONFIG_SMALL("FFM (AVserver live feed)"),
.priv_data_size = sizeof(FFMContext),
.read_probe = ffm_probe,
.read_header = ffm_read_header,
.read_packet = ffm_read_packet,
.read_close = ffm_close,
.read_seek = ffm_seek,
};

@ -1,249 +0,0 @@
/*
* FFM (avserver live feed) muxer
* Copyright (c) 2001 Fabrice Bellard
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "avformat.h"
#include "internal.h"
#include "ffm.h"
static void flush_packet(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
int fill_size, h;
AVIOContext *pb = s->pb;
fill_size = ffm->packet_end - ffm->packet_ptr;
memset(ffm->packet_ptr, 0, fill_size);
assert(avio_tell(pb) % ffm->packet_size == 0);
/* put header */
avio_wb16(pb, PACKET_ID);
avio_wb16(pb, fill_size);
avio_wb64(pb, ffm->dts);
h = ffm->frame_offset;
if (ffm->first_packet)
h |= 0x8000;
avio_wb16(pb, h);
avio_write(pb, ffm->packet, ffm->packet_end - ffm->packet);
avio_flush(pb);
/* prepare next packet */
ffm->frame_offset = 0; /* no key frame */
ffm->packet_ptr = ffm->packet;
ffm->first_packet = 0;
}
/* 'first' is true if first data of a frame */
static void ffm_write_data(AVFormatContext *s,
const uint8_t *buf, int size,
int64_t dts, int header)
{
FFMContext *ffm = s->priv_data;
int len;
if (header && ffm->frame_offset == 0) {
ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
ffm->dts = dts;
}
/* write as many packets as needed */
while (size > 0) {
len = ffm->packet_end - ffm->packet_ptr;
if (len > size)
len = size;
memcpy(ffm->packet_ptr, buf, len);
ffm->packet_ptr += len;
buf += len;
size -= len;
if (ffm->packet_ptr >= ffm->packet_end)
flush_packet(s);
}
}
static int ffm_write_header(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
AVStream *st;
AVIOContext *pb = s->pb;
AVCodecContext *codec;
int bit_rate, i;
ffm->packet_size = FFM_PACKET_SIZE;
/* header */
avio_wl32(pb, MKTAG('F', 'F', 'M', '1'));
avio_wb32(pb, ffm->packet_size);
avio_wb64(pb, 0); /* current write position */
avio_wb32(pb, s->nb_streams);
bit_rate = 0;
for(i=0;i<s->nb_streams;i++) {
st = s->streams[i];
bit_rate += st->codec->bit_rate;
}
avio_wb32(pb, bit_rate);
/* list of streams */
for(i=0;i<s->nb_streams;i++) {
st = s->streams[i];
avpriv_set_pts_info(st, 64, 1, 1000000);
codec = st->codec;
/* generic info */
avio_wb32(pb, codec->codec_id);
avio_w8(pb, codec->codec_type);
avio_wb32(pb, codec->bit_rate);
avio_wb32(pb, codec->flags);
avio_wb32(pb, codec->flags2);
avio_wb32(pb, codec->debug);
/* specific info */
switch(codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
avio_wb32(pb, codec->time_base.num);
avio_wb32(pb, codec->time_base.den);
avio_wb16(pb, codec->width);
avio_wb16(pb, codec->height);
avio_wb16(pb, codec->gop_size);
avio_wb32(pb, codec->pix_fmt);
avio_w8(pb, codec->qmin);
avio_w8(pb, codec->qmax);
avio_w8(pb, codec->max_qdiff);
avio_wb16(pb, (int) (codec->qcompress * 10000.0));
avio_wb16(pb, (int) (codec->qblur * 10000.0));
avio_wb32(pb, codec->bit_rate_tolerance);
avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp");
avio_wb32(pb, codec->rc_max_rate);
avio_wb32(pb, codec->rc_min_rate);
avio_wb32(pb, codec->rc_buffer_size);
avio_wb64(pb, av_double2int(codec->i_quant_factor));
avio_wb64(pb, av_double2int(codec->b_quant_factor));
avio_wb64(pb, av_double2int(codec->i_quant_offset));
avio_wb64(pb, av_double2int(codec->b_quant_offset));
avio_wb32(pb, codec->dct_algo);
avio_wb32(pb, codec->strict_std_compliance);
avio_wb32(pb, codec->max_b_frames);
avio_wb32(pb, codec->mpeg_quant);
avio_wb32(pb, codec->intra_dc_precision);
avio_wb32(pb, codec->me_method);
avio_wb32(pb, codec->mb_decision);
avio_wb32(pb, codec->nsse_weight);
avio_wb32(pb, codec->frame_skip_cmp);
avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity));
avio_wb32(pb, codec->codec_tag);
avio_w8(pb, codec->thread_count);
avio_wb32(pb, codec->coder_type);
avio_wb32(pb, codec->me_cmp);
avio_wb32(pb, codec->me_subpel_quality);
avio_wb32(pb, codec->me_range);
avio_wb32(pb, codec->keyint_min);
avio_wb32(pb, codec->scenechange_threshold);
avio_wb32(pb, codec->b_frame_strategy);
avio_wb64(pb, av_double2int(codec->qcompress));
avio_wb64(pb, av_double2int(codec->qblur));
avio_wb32(pb, codec->max_qdiff);
avio_wb32(pb, codec->refs);
break;
case AVMEDIA_TYPE_AUDIO:
avio_wb32(pb, codec->sample_rate);
avio_wl16(pb, codec->channels);
avio_wl16(pb, codec->frame_size);
break;
default:
return -1;
}
if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
avio_wb32(pb, codec->extradata_size);
avio_write(pb, codec->extradata, codec->extradata_size);
}
}
/* flush until end of block reached */
while ((avio_tell(pb) % ffm->packet_size) != 0)
avio_w8(pb, 0);
avio_flush(pb);
/* init packet mux */
ffm->packet_ptr = ffm->packet;
ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
assert(ffm->packet_end >= ffm->packet);
ffm->frame_offset = 0;
ffm->dts = 0;
ffm->first_packet = 1;
return 0;
}
static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt)
{
int64_t dts;
uint8_t header[FRAME_HEADER_SIZE+4];
int header_size = FRAME_HEADER_SIZE;
dts = pkt->dts;
/* packet size & key_frame */
header[0] = pkt->stream_index;
header[1] = 0;
if (pkt->flags & AV_PKT_FLAG_KEY)
header[1] |= FLAG_KEY_FRAME;
AV_WB24(header+2, pkt->size);
AV_WB24(header+5, pkt->duration);
AV_WB64(header+8, pkt->pts);
if (pkt->pts != pkt->dts) {
header[1] |= FLAG_DTS;
AV_WB32(header+16, pkt->pts - pkt->dts);
header_size += 4;
}
ffm_write_data(s, header, header_size, dts, 1);
ffm_write_data(s, pkt->data, pkt->size, dts, 0);
return 0;
}
static int ffm_write_trailer(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
/* flush packets */
if (ffm->packet_ptr > ffm->packet)
flush_packet(s);
return 0;
}
AVOutputFormat ff_ffm_muxer = {
.name = "ffm",
.long_name = NULL_IF_CONFIG_SMALL("FFM (AVserver live feed)"),
.mime_type = "",
.extensions = "ffm",
.priv_data_size = sizeof(FFMContext),
.audio_codec = AV_CODEC_ID_MP2,
.video_codec = AV_CODEC_ID_MPEG1VIDEO,
.write_header = ffm_write_header,
.write_packet = ffm_write_packet,
.write_trailer = ffm_write_trailer,
.flags = AVFMT_TS_NEGATIVE,
};

@ -6,7 +6,6 @@ FATE_LAVF-$(call ENCDEC2, MPEG4, MP2, AVI) += avi
FATE_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp FATE_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp
FATE_LAVF-$(call ENCDEC, DPX, IMAGE2) += dpx FATE_LAVF-$(call ENCDEC, DPX, IMAGE2) += dpx
FATE_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt FATE_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt
FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm
FATE_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt FATE_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt
FATE_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif FATE_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif
FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf

@ -151,7 +151,6 @@ FATE_SEEK_LAVF-$(call ENCDEC, PCM_S16BE, AU) += au
FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, MP2, AVI) += avi FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, MP2, AVI) += avi
FATE_SEEK_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp FATE_SEEK_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp
FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt
FATE_SEEK_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm
FATE_SEEK_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt FATE_SEEK_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt
FATE_SEEK_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif FATE_SEEK_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif
FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf
@ -188,7 +187,6 @@ fate-seek-lavf-au: SRC = lavf/lavf.au
fate-seek-lavf-avi: SRC = lavf/lavf.avi fate-seek-lavf-avi: SRC = lavf/lavf.avi
fate-seek-lavf-bmp: SRC = images/bmp/%02d.bmp fate-seek-lavf-bmp: SRC = images/bmp/%02d.bmp
fate-seek-lavf-dv_fmt: SRC = lavf/lavf.dv fate-seek-lavf-dv_fmt: SRC = lavf/lavf.dv
fate-seek-lavf-ffm: SRC = lavf/lavf.ffm
fate-seek-lavf-flv_fmt: SRC = lavf/lavf.flv fate-seek-lavf-flv_fmt: SRC = lavf/lavf.flv
fate-seek-lavf-gif: SRC = lavf/lavf.gif fate-seek-lavf-gif: SRC = lavf/lavf.gif
fate-seek-lavf-gxf: SRC = lavf/lavf.gxf fate-seek-lavf-gxf: SRC = lavf/lavf.gxf

@ -78,10 +78,6 @@ if [ -n "$do_swf" ] ; then
do_lavf swf "" "-an" do_lavf swf "" "-an"
fi fi
if [ -n "$do_ffm" ] ; then
do_lavf ffm "" "-ar 44100"
fi
if [ -n "$do_flv_fmt" ] ; then if [ -n "$do_flv_fmt" ] ; then
do_lavf flv "" "-an" do_lavf flv "" "-an"
fi fi

@ -1,3 +0,0 @@
f3f0c42283b75bc826f499f048085c27 *./tests/data/lavf/lavf.ffm
376832 ./tests/data/lavf/lavf.ffm
./tests/data/lavf/lavf.ffm CRC=0xdd24439e

@ -1,53 +0,0 @@
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st:-1 flags:1 ts: 1.894167
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 0 flags:0 ts: 0.788334
ret: 0 st: 1 flags:1 dts: 0.772766 pts: 0.772766 pos: 315392 size: 209
ret: 0 st: 0 flags:1 ts:-0.317499
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st: 1 flags:0 ts: 2.576668
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 1 flags:1 ts: 1.470835
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st:-1 flags:0 ts: 0.365002
ret: 0 st: 1 flags:1 dts: 0.328685 pts: 0.328685 pos: 155648 size: 209
ret: 0 st:-1 flags:1 ts:-0.740831
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st: 0 flags:0 ts: 2.153336
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 0 flags:1 ts: 1.047503
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 1 flags:0 ts:-0.058330
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st: 1 flags:1 ts: 2.835837
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st:-1 flags:0 ts: 1.730004
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st:-1 flags:1 ts: 0.624171
ret: 0 st: 1 flags:1 dts: 0.642154 pts: 0.642154 pos: 274432 size: 209
ret: 0 st: 0 flags:0 ts:-0.481662
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st: 0 flags:1 ts: 2.412505
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 1 flags:0 ts: 1.306672
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 1 flags:1 ts: 0.200839
ret: 0 st: 1 flags:1 dts: 0.224195 pts: 0.224195 pos: 114688 size: 209
ret: 0 st:-1 flags:0 ts:-0.904994
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st:-1 flags:1 ts: 1.989173
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 0 flags:0 ts: 0.883340
ret: 0 st: 1 flags:1 dts: 0.877256 pts: 0.877256 pos: 339968 size: 209
ret: 0 st: 0 flags:1 ts:-0.222493
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
ret: 0 st: 1 flags:0 ts: 2.671674
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st: 1 flags:1 ts: 1.565841
ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209
ret: 0 st:-1 flags:0 ts: 0.460008
ret: 0 st: 1 flags:1 dts: 0.459297 pts: 0.459297 pos: 204800 size: 209
ret: 0 st:-1 flags:1 ts:-0.645825
ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24664
Loading…
Cancel
Save