greately improved: video is now played but nginx crashed on some (big?) frames

This commit is contained in:
Roman Arutyunyan 2012-03-16 22:09:04 +04:00
parent 65cc92e7ca
commit fd9e64c138
10 changed files with 1452 additions and 157 deletions

2
TODO
View file

@ -1,5 +1,7 @@
- implement chain-reuse for output
- move shared bufs-related code to a separate .c
- get rid of greedy send_chain
- remove macros hell from ngx_rtmp_send.c

990
doc/flv.html Normal file
View file

@ -0,0 +1,990 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0022)http://osflash.org/flv -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>
flv [Open Source Flash]
</title>
<meta name="generator" content="DokuWiki">
<meta name="robots" content="index,follow">
<meta name="date" content="2011-12-02T01:16:59-0500">
<meta name="keywords" content="flv">
<link rel="search" type="application/opensearchdescription+xml" href="http://osflash.org/lib/exe/opensearch.php" title="Open Source Flash">
<link rel="start" href="http://osflash.org/">
<link rel="contents" href="http://osflash.org/flv?do=index" title="Sitemap">
<link rel="alternate" type="application/rss+xml" title="Recent Changes" href="http://osflash.org/feed.php">
<link rel="alternate" type="application/rss+xml" title="Current Namespace" href="http://osflash.org/feed.php?mode=list&ns=">
<link rel="edit" title="Edit this page" href="http://osflash.org/flv?do=edit">
<link rel="alternate" type="text/html" title="Plain HTML" href="http://osflash.org/_export/xhtml/flv">
<link rel="alternate" type="text/plain" title="Wiki Markup" href="http://osflash.org/_export/raw/flv">
<link rel="canonical" href="./flv_files/flv.html">
<link rel="stylesheet" media="screen" type="text/css" href="./flv_files/css.php">
<link rel="stylesheet" media="all" type="text/css" href="./flv_files/css(1).php">
<link rel="stylesheet" media="print" type="text/css" href="./flv_files/css(2).php">
<script type="text/javascript"><!--//--><![CDATA[//><!--
var NS='';var JSINFO = {"id":"flv","namespace":""};
//--><!]]></script>
<script type="text/javascript" charset="utf-8" src="./flv_files/js.php"></script>
<link rel="shortcut icon" href="http://osflash.org/lib/tpl/default/images/favicon.ico">
<style type="text/css">.recaptchatable td img{display:block}.recaptchatable .recaptcha_r1_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') 0 -63px no-repeat;width:318px;height:9px}.recaptchatable .recaptcha_r2_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -18px 0 no-repeat;width:9px;height:57px}.recaptchatable .recaptcha_r2_c2{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -27px 0 no-repeat;width:9px;height:57px}.recaptchatable .recaptcha_r3_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') 0 0 no-repeat;width:9px;height:63px}.recaptchatable .recaptcha_r3_c2{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -18px -57px no-repeat;width:300px;height:6px}.recaptchatable .recaptcha_r3_c3{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -9px 0 no-repeat;width:9px;height:63px}.recaptchatable .recaptcha_r4_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -43px 0 no-repeat;width:171px;height:49px}.recaptchatable .recaptcha_r4_c2{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -36px 0 no-repeat;width:7px;height:57px}.recaptchatable .recaptcha_r4_c4{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -214px 0 no-repeat;width:97px;height:57px}.recaptchatable .recaptcha_r7_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -43px -49px no-repeat;width:171px;height:8px}.recaptchatable .recaptcha_r8_c1{background:url('http://www.google.com/recaptcha/api/img/white/sprite.png') -43px -49px no-repeat;width:25px;height:8px}.recaptchatable .recaptcha_image_cell center img{height:57px}.recaptchatable .recaptcha_image_cell center{height:57px}.recaptchatable .recaptcha_image_cell{background-color:white;height:57px}#recaptcha_area,#recaptcha_table{width:318px!important}.recaptchatable,#recaptcha_area tr,#recaptcha_area td,#recaptcha_area th{margin:0!important;border:0!important;padding:0!important;border-collapse:collapse!important;vertical-align:middle!important}.recaptchatable *{margin:0;padding:0;border:0;font-family:helvetica,sans-serif;font-size:8pt;color:black;position:static;top:auto;left:auto;right:auto;bottom:auto;text-align:left!important}.recaptchatable #recaptcha_image{margin:auto}.recaptchatable img{border:0!important;margin:0!important;padding:0!important}.recaptchatable a,.recaptchatable a:hover{outline:none;border:0!important;padding:0!important;text-decoration:none;color:blue;background:none!important;font-weight:normal}.recaptcha_input_area{position:relative!important;width:146px!important;height:45px!important;margin-left:20px!important;margin-right:5px!important;margin-top:4px!important;background:none!important}.recaptchatable label.recaptcha_input_area_text{margin:0!important;padding:0!important;position:static!important;top:auto!important;left:auto!important;right:auto!important;bottom:auto!important;background:none!important;height:auto!important;width:auto!important}.recaptcha_theme_red label.recaptcha_input_area_text,.recaptcha_theme_white label.recaptcha_input_area_text{color:black!important}.recaptcha_theme_blackglass label.recaptcha_input_area_text{color:white!important}.recaptchatable #recaptcha_response_field{width:145px!important;position:absolute!important;bottom:7px!important;padding:0!important;margin:0!important;font-size:10pt}.recaptcha_theme_blackglass #recaptcha_response_field,.recaptcha_theme_white #recaptcha_response_field{border:1px solid gray}.recaptcha_theme_red #recaptcha_response_field{border:1px solid #cca940}.recaptcha_audio_cant_hear_link{font-size:7pt;color:black}.recaptchatable{line-height:1em}#recaptcha_instructions_error{color:red!important}
.recaptcha_is_showing_audio .recaptcha_only_if_image,.recaptcha_isnot_showing_audio .recaptcha_only_if_audio,.recaptcha_had_incorrect_sol .recaptcha_only_if_no_incorrect_sol,.recaptcha_nothad_incorrect_sol .recaptcha_only_if_incorrect_sol{display:none !important}</style></head>
<body>
<div class="dokuwiki">
<div class="stylehead">
<div class="header">
<div class="pagename">
[[<a href="http://osflash.org/flv?do=backlink" title="Backlinks">flv</a>]]
</div>
<div class="logo">
<a href="http://osflash.org/" name="dokuwiki__top" id="dokuwiki__top" accesskey="h" title="[H]">Open Source Flash</a> </div>
<div class="clearer"></div>
</div>
<div class="bar" id="bar__top">
<div class="bar-left" id="bar__topleft">
<form class="button btn_edit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value=""><input type="submit" value="Edit this page" class="button" accesskey="e" title="Edit this page [E]"></div></form> <form class="button btn_revs" method="get" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="revisions"><input type="submit" value="Old revisions" class="button" accesskey="o" title="Old revisions [O]"></div></form> </div>
<div class="bar-right" id="bar__topright">
<form class="button btn_recent" method="get" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="recent"><input type="submit" value="Recent changes" class="button" accesskey="r" title="Recent changes [R]"></div></form> <form action="http://osflash.org/" accept-charset="utf-8" class="search" id="dw__search" method="get"><div class="no"><input type="hidden" name="do" value="search"><input type="text" id="qsearch__in" accesskey="f" name="id" class="edit" title="[F]"><input type="submit" value="Search" class="button" title="Search"><div id="qsearch__out" class="ajax_qsearch JSpopup"></div></div></form>&nbsp;
</div>
<div class="clearer"></div>
</div>
<div class="breadcrumbs">
<span class="bchead">Trace:</span> <span class="bcsep">»</span> <span class="curid"><a href="./flv_files/flv.html" class="breadcrumbs" title="flv">flv</a></span> </div>
</div>
<div class="page">
<!-- wikipage start -->
<!-- TOC START -->
<div class="toc">
<div class="tocheader toctoggle" id="toc__header">Table of Contents</div>
<div id="toc__inside">
<ul class="toc">
<li class="level1"><div class="li"><span class="li"><a href="http://osflash.org/flv#flash_video_flv" class="toc">Flash Video (FLV)</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#overview" class="toc">Overview</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#issues" class="toc">Issues</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#video" class="toc">Video</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#audio" class="toc">Audio</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#image" class="toc">Image</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#metadata" class="toc">Metadata</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#flv_format" class="toc">FLV Format</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="http://osflash.org/flv#http_streaming" class="toc">HTTP Streaming</a></span></div></li>
</ul>
</li>
<li class="level1"><div class="li"><span class="li"><a href="http://osflash.org/flv#discussion__section" class="toc">Discussion</a></span></div></li></ul>
</div>
</div>
<!-- TOC END -->
<h1 class="sectionedit1"><a name="flash_video_flv" id="flash_video_flv">Flash Video (FLV)</a></h1>
<div class="level1">
<p>
Flash Video is the name of a file format used to deliver video over the Internet using Adobe Flash Player version 6 or newer. Flash Video content may also be embedded within SWF files. Until version 9 update 3 of the Flash Player, Flash Video referred to a proprietary file format, having the extension .FLV but Adobe introduced <a href="http://www.kaourantin.net/2007/10/new-file-extensions-and-mime-types.html" class="urlextern" title="http://www.kaourantin.net/2007/10/new-file-extensions-and-mime-types.html" rel="nofollow">new file extensions and MIME types</a> and suggests to use those instead of the old FLV:
</p>
<div class="table sectionedit2"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> File Extension </th><th class="col1 leftalign"> <a href="http://ftyps.com/" class="urlextern" title="http://ftyps.com/" rel="nofollow">FTYP</a> </th><th class="col2 leftalign"> <a href="http://www.adobe.com/go/tn_19439" class="urlextern" title="http://www.adobe.com/go/tn_19439" rel="nofollow">MIME Type</a> </th><th class="col3 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> .f4v </td><td class="col1 leftalign"> 'F4V ' </td><td class="col2 leftalign"> video/mp4 </td><td class="col3 leftalign"> Video for Adobe Flash Player </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> .f4p </td><td class="col1 leftalign"> 'F4P ' </td><td class="col2 leftalign"> video/mp4 </td><td class="col3 leftalign"> Protected Media for Adobe Flash Player </td>
</tr>
<tr class="row3">
<td class="col0 leftalign"> .f4a </td><td class="col1 leftalign"> 'F4A ' </td><td class="col2 leftalign"> video/mp4 </td><td class="col3 leftalign"> Audio for Adobe Flash Player </td>
</tr>
<tr class="row4">
<td class="col0 leftalign"> .f4b </td><td class="col1 leftalign"> 'F4B ' </td><td class="col2 leftalign"> video/mp4 </td><td class="col3 leftalign"> Audio Book for Adobe Flash Player </td>
</tr>
<tr class="row5">
<td class="col0 leftalign"> .flv </td><td class="col1 leftalign"> </td><td class="col2 leftalign"> video/x-flv </td><td class="col3 leftalign"> <a href="http://en.wikipedia.org/wiki/Flash_Video" class="urlextern" title="http://en.wikipedia.org/wiki/Flash_Video" rel="nofollow">Flash Video</a> </td>
</tr>
</tbody></table></div>
<p>
It is possible to place H.264 and AAC streams into the traditional FLV file, but Adobe strongly encourages everyone to embrace the new standard file format. There are functional limits with the FLV structure when streaming H.264 which couldn't be overcome without a redesign of the file format. This is one of the reasons Adobe is moving away from the traditional FLV file structure. Specifically dealing with sequence headers and enders is tricky with FLV streams. Adobe is still working out if it's possible to place On2 VP6 streams into the new file format.
</p>
</div>
<div class="secedit editbutton_section editbutton_1"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Flash Video (FLV)] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="1-1923"><input type="submit" value="Edit" class="button" title="Flash Video (FLV)"></div></form></div>
<h2 class="sectionedit3"><a name="overview" id="overview">Overview</a></h2>
<div class="level2">
<ul>
<li class="level1"><div class="li"> File format parser implementing parts of <a href="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-12" class="urlextern" title="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-12" rel="nofollow">ISO 14496-12</a> (very limited sub set of <a href="http://en.wikipedia.org/wiki/MPEG-4" class="urlextern" title="http://en.wikipedia.org/wiki/MPEG-4" rel="nofollow">MPEG-4</a>, 3GP and QuickTime movie support).</div>
</li>
<li class="level1"><div class="li"> Support for the 3GPP timed text specification <a href="http://www.3gpp.org/ftp/Specs/html-info/26245.htm" class="urlextern" title="http://www.3gpp.org/ftp/Specs/html-info/26245.htm" rel="nofollow">3GPP TS 26.245</a>. Essentially this is a standardized subtitle format within <a href="http://en.wikipedia.org/wiki/3GP" class="urlextern" title="http://en.wikipedia.org/wiki/3GP" rel="nofollow">3GP</a> files. Any number of text tracks are supported and all the information, including esoteric stuff like karaoke meta data is dumped in 'onMetaData' and a new 'onTextData' NetStream callback. Language information in the individual tracks is also reported. That means you can have sub titles in several languages. Check the <a href="http://www.3gpp.org/ftp/Specs/html-info/26245.htm" class="urlextern" title="http://www.3gpp.org/ftp/Specs/html-info/26245.htm" rel="nofollow">3GPP TS 26.245</a> specification to see what information is available. Note that you have to take care of the formatting and placement of the text yourself, the Flash Player will do nothing here. You can use <a href="http://gpac.sourceforge.net/doc_ttxt.php" class="urlextern" title="http://gpac.sourceforge.net/doc_ttxt.php" rel="nofollow">MP4Box</a> to inject text data into existing files.</div>
</li>
<li class="level1"><div class="li"> Partial parsing support for the <a href="http://atomicparsley.sourceforge.net/mpeg-4files.html" class="urlextern" title="http://atomicparsley.sourceforge.net/mpeg-4files.html" rel="nofollow">'ilst' atom</a> which is the ID3 equivalent iTunes uses to store meta data. This is usually present in iTunes files. It contains ID3 like information and is reported in the onMetaData callback as key/value pairs in a mixed array with the name 'tags'. ID3V2 is not supported right now.</div>
</li>
<li class="level1"><div class="li"> A software based <a href="http://en.wikipedia.org/wiki/H264" class="urlextern" title="http://en.wikipedia.org/wiki/H264" rel="nofollow">H.264</a> codec with the ability to decode Base, Mainline and High profiles.</div>
</li>
<li class="level1"><div class="li"> An <a href="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" class="urlextern" title="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" rel="nofollow">AAC</a> decoder supporting AAC Main, AAC LC and SBR (also known as HE-AAC <sup><a href="http://osflash.org/flv#fn__1" name="fnt__1" id="fnt__1" class="fn_top">1)</a></sup>. </div>
</li>
</ul>
</div>
<div class="secedit editbutton_section editbutton_3"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Overview] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="1924-4103"><input type="submit" value="Edit" class="button" title="Overview"></div></form></div>
<h2 class="sectionedit4"><a name="issues" id="issues">Issues</a></h2>
<div class="level2">
<p>
Tools to solve FLV-related issues:
</p>
<ul>
<li class="level1"><div class="li"> <a href="http://labs.adobe.com/downloads/flvcheck.html" class="urlextern" title="http://labs.adobe.com/downloads/flvcheck.html" rel="nofollow">Utility for checking FLV format</a></div>
</li>
<li class="level1"><div class="li"> <a href="http://www.buraks.com/flvmdi/" class="urlextern" title="http://www.buraks.com/flvmdi/" rel="nofollow">FLV Metadata Injector</a> - free closed-source tool which can inject metadata information into a FLV file</div>
</li>
</ul>
</div>
<div class="secedit editbutton_section editbutton_4"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Issues] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="4104-4385"><input type="submit" value="Edit" class="button" title="Issues"></div></form></div>
<h2 class="sectionedit5"><a name="video" id="video">Video</a></h2>
<div class="level2">
</div>
<h4><a name="overview1" id="overview1">Overview</a></h4>
<div class="level4">
<p>
You load and play .mp4,.m4v,.m4a,.mov and .3gp files using the same NetStream <acronym title="Application Programming Interface">API</acronym> you use to load FLV files. There are a few things to be aware of:
</p>
<ul>
<li class="level1"><div class="li"> Video needs to be in H.264 format only. <acronym title="Motion Picture Experts Group">MPEG</acronym>-4 Part 2 (Xvid, DivX etc.) video is not supported, H.263 video is not supported, Sorenson Video is not supported. A lot of pod casts are still using <acronym title="Motion Picture Experts Group">MPEG</acronym>-4 Part 2 so do not be surprised if you do not see any video. </div>
</li>
<li class="level1"><div class="li"> the Flash Player is close to 100% compliant to the H.264 standard, all Base, Main, High and High 10 bit streams should play. </div>
</li>
<li class="level1"><div class="li"> Extended, High 4:2:2 and High 4:4:4 profiles are not officially supported at this time. They might or might not work depending on what features are used. There are no artificial lower limit on B-frames or any problems with B-pyramids like other players do. </div>
</li>
<li class="level1"><div class="li"> Since these files contain an index unlike old FLV files, the Flash Player provides a list of save seek points, e.g. times you can seek to without having the play head jump around. You'll get this information through the onMetaData callback in an array with the name 'seekpoints'. On the downside, some files are missing this information which also means that these files are not seekable at all! This is very different from the traditional FLV file format which is rather based on the notion of key frames to determine the seek points. </div>
</li>
</ul>
</div>
<h4><a name="codecs" id="codecs">Codecs</a></h4>
<div class="level4">
<div class="table sectionedit6"><table class="inline">
<tbody><tr class="row0">
<th class="col0"> Codec </th><th class="col1"> Introduced in Flash Player version </th><th class="col2"> Introduced in Flash Lite version </th><th class="col3"> Container Formats </th><th class="col4"> <acronym title="International Organization for Standardization">ISO</acronym> Specification </th><th class="col5"> Codec Id </th>
</tr>
<tr class="row1">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/Sorenson_codec" class="urlextern" title="http://en.wikipedia.org/wiki/Sorenson_codec" rel="nofollow"> Sorenson Spark</a> <sup><a href="http://osflash.org/flv#fn__2" name="fnt__2" id="fnt__2" class="fn_top">2)</a></sup> </td><td class="col1"> 6 </td><td class="col2"> 3 </td><td class="col3"> FLV </td><td class="col4"> </td><td class="col5"> 2 </td>
</tr>
<tr class="row2">
<td class="col0"> Macromedia Screen Video <sup><a href="http://osflash.org/flv#fn__3" name="fnt__3" id="fnt__3" class="fn_top">3)</a></sup> </td><td class="col1"> 6 </td><td class="col2"> - </td><td class="col3"> FLV </td><td class="col4"> </td><td class="col5"> 3 </td>
</tr>
<tr class="row3">
<td class="col0"> Macromedia ScreenVideo 2 <sup><a href="http://osflash.org/flv#fn__4" name="fnt__4" id="fnt__4" class="fn_top">4)</a></sup> </td><td class="col1"> 8 </td><td class="col2"> - </td><td class="col3"> FLV </td><td class="col4"> </td><td class="col5"> 6 </td>
</tr>
<tr class="row4">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/VP6" class="urlextern" title="http://en.wikipedia.org/wiki/VP6" rel="nofollow">On2 TrueMotion VP6-E</a> </td><td class="col1"> 8 </td><td class="col2"> 3 </td><td class="col3"> MOV </td><td class="col4"> </td><td class="col5"> 4 </td>
</tr>
<tr class="row5">
<td class="col0"> <a href="http://www.on2.com/index.php?358" class="urlextern" title="http://www.on2.com/index.php?358" rel="nofollow">On2 TrueMotion VP6-S</a> </td><td class="col1"> 9.0.115.0 </td><td class="col2"> - </td><td class="col3"> MP4V, M4V </td><td class="col4"> </td><td class="col5"> 5 </td>
</tr>
<tr class="row6">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/H.264" class="urlextern" title="http://en.wikipedia.org/wiki/H.264" rel="nofollow">H.264</a> (<acronym title="Motion Picture Experts Group">MPEG</acronym>-4 Part 10) </td><td class="col1"> 9.0.115.0 </td><td class="col2"> - </td><td class="col3"> MP4, F4V, 3GP, 3G2 </td><td class="col4"> <a href="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-10" class="urlextern" title="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-10" rel="nofollow">ISO 14496-10</a> </td><td class="col5"> </td>
</tr>
</tbody></table></div>
<p>
<a href="http://kb.adobe.com/selfservice/viewContent.do?externalId=kb402866&sliceId=1" class="urlextern" title="http://kb.adobe.com/selfservice/viewContent.do?externalId=kb402866&amp;sliceId=1" rel="nofollow">Adobe Tech Note</a>
</p>
</div>
<div class="secedit editbutton_section editbutton_5"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Video] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="4386-8088"><input type="submit" value="Edit" class="button" title="Video"></div></form></div>
<h2 class="sectionedit7"><a name="audio" id="audio">Audio</a></h2>
<div class="level2">
</div>
<h4><a name="overview2" id="overview2">Overview</a></h4>
<div class="level4">
<ul>
<li class="level1"><div class="li"> Audio can be either <a href="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" class="urlextern" title="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" rel="nofollow">AAC</a> Main, AAC LC or SBR, corresponding to audio object types 0, 1 and 2. </div>
</li>
<li class="level1"><div class="li"> The '.mp3' sample type for tracks with mp3 audio is also supported. </div>
</li>
<li class="level1"><div class="li"> MP3inMP4 which intends to do multi-channel mp3 playback within mp4 files is not supported. </div>
</li>
<li class="level1"><div class="li"> The old QuickTime specific style of embedding AAC and <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym> data is not supported. It is unlikely though that you will run into these kind of files.</div>
</li>
<li class="level1"><div class="li"> Unencrypted audio book files contain chapter information. This information is exposed in the onMetaData callback as an array of objects with name 'chapters'.</div>
</li>
<li class="level1"><div class="li"> The Flash Player can play back multi-channel AAC files, though the sound is mixed down to two channels and resampled to 44.1Khz. Multi channel playback is targeted for one of the next major revisions of the Flash Player. This requires complete redesign of the sound engine in the Flash Player which dates from circa 1996 and has not been improved since.</div>
</li>
<li class="level1"><div class="li"> All sampling rates from 8Khz to 96Khz are supported. A 32 tap <a href="http://en.wikipedia.org/wiki/Kaiser_window" class="urlextern" title="http://en.wikipedia.org/wiki/Kaiser_window" rel="nofollow">Kaiser Bessel</a> based FIR filter which resamples the sound to 44.1Khz, retaining high quality. The most common sample rate combinations have a hard coded number of phases. In case of a 48000 to 44100 Hz conversion the filter has 147 phases f.ex. </div>
</li>
<li class="level1"><div class="li"> Flash Player Update 3 Beta 2 now can play back any <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym> sampling rate leveraging the same AAC implementation. No more chipmunks. Ever.</div>
</li>
</ul>
</div>
<h4><a name="codecs1" id="codecs1">Codecs</a></h4>
<div class="level4">
<div class="table sectionedit8"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Codec </th><th class="col1"> Introduced in Flash Player version </th><th class="col2"> Container Formats </th><th class="col3"> <acronym title="International Organization for Standardization">ISO</acronym> Specification </th><th class="col4"> Codec Id </th>
</tr>
<tr class="row1">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/MP3" class="urlextern" title="http://en.wikipedia.org/wiki/MP3" rel="nofollow"> MP3</a> </td><td class="col1"> 6 </td><td class="col2"> <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym> </td><td class="col3"> </td><td class="col4"> 2 </td>
</tr>
<tr class="row2">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/Nellymoser" class="urlextern" title="http://en.wikipedia.org/wiki/Nellymoser" rel="nofollow">Nellymoser ASAO Codec</a> (speech compression) audio content </td><td class="col1"> 6 </td><td class="col2"> FLV </td><td class="col3"> </td><td class="col4"> 5, 6 </td>
</tr>
<tr class="row3">
<td class="col0"> Raw <a href="http://en.wikipedia.org/wiki/PCM" class="urlextern" title="http://en.wikipedia.org/wiki/PCM" rel="nofollow">PCM</a> sampled audio content </td><td class="col1"> 6 </td><td class="col2"> WAV </td><td class="col3"> </td><td class="col4"> 0 </td>
</tr>
<tr class="row4">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/ADPCM" class="urlextern" title="http://en.wikipedia.org/wiki/ADPCM" rel="nofollow"> ADPCM</a> (Adaptive Delta Pulse Code Modulation) audio content </td><td class="col1"> 6 </td><td class="col2"> </td><td class="col3"> </td><td class="col4"> 1 </td>
</tr>
<tr class="row5">
<td class="col0"> <a href="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" class="urlextern" title="http://en.wikipedia.org/wiki/Advanced_Audio_Coding" rel="nofollow">AAC</a> (<a href="http://en.wikipedia.org/wiki/HE-AAC" class="urlextern" title="http://en.wikipedia.org/wiki/HE-AAC" rel="nofollow">HE-AAC</a>/AAC <a href="http://en.wikipedia.org/wiki/Spectral_Band_Replication" class="urlextern" title="http://en.wikipedia.org/wiki/Spectral_Band_Replication" rel="nofollow">SBR</a>, AAC Main Profile, and AAC-LC) </td><td class="col1"> 9.0.115.0 </td><td class="col2"> M4A, MP4 </td><td class="col3"> <a href="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-3" class="urlextern" title="http://www.iso.org/iso/en/CombinedQueryResult.CombinedQueryResult?queryString=14496-3" rel="nofollow">ISO 14496-3</a> </td><td class="col4"> </td>
</tr>
<tr class="row6">
<td class="col0"> Speex </td><td class="col1"> 10 </td><td class="col2"> FLV </td><td class="col3"> <a href="http://en.wikipedia.org/wiki/Speex" class="urlextern" title="http://en.wikipedia.org/wiki/Speex" rel="nofollow">Wiki</a> </td><td class="col4"> 11 </td>
</tr>
</tbody></table></div>
</div>
<div class="secedit editbutton_section editbutton_7"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Audio] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="8089-10530"><input type="submit" value="Edit" class="button" title="Audio"></div></form></div>
<h2 class="sectionedit9"><a name="image" id="image">Image</a></h2>
<div class="level2">
<ul>
<li class="level1"><div class="li"> Image tracks encoded in <acronym title="Joint Photographics Experts Group">JPEG</acronym>, <acronym title="Graphics Interchange Format">GIF</acronym> and <acronym title="Portable Network Graphics">PNG</acronym> are accessible in AS3 as a byte array through the callback 'onImageData'. You can simply take that byte array and use the Loader class to display the images. Most often these images represent cover artwork for audio files. </div>
</li>
<li class="level1"><div class="li"> <acronym title="Tagged Image File Format">TIFF</acronym> image tracks are not supported, you might come across files using this. </div>
</li>
<li class="level1"><div class="li"> Support for the 'covr' meta data stored in iTunes files, accessible as byte arrays.</div>
</li>
</ul>
</div>
<div class="secedit editbutton_section editbutton_9"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Image] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="10531-10990"><input type="submit" value="Edit" class="button" title="Image"></div></form></div>
<h2 class="sectionedit10"><a name="metadata" id="metadata">Metadata</a></h2>
<div class="level2">
<div class="table sectionedit11"><table class="inline">
<tbody><tr class="row0">
<th class="col0"> Property </th><th class="col1"> Value </th><th class="col2"> Notes </th>
</tr>
<tr class="row1">
<td class="col0"> duration </td><td class="col1 leftalign"> Obvious. </td><td class="col2 leftalign"> Unlike for FLV files this field will always be present. </td>
</tr>
<tr class="row2">
<td class="col0"> videocodecid </td><td class="col1 leftalign"> For H.264 it reports 'avc1'. </td><td class="col2"> </td>
</tr>
<tr class="row3">
<td class="col0"> audiocodecid </td><td class="col1 leftalign"> For AAC it reports 'mp4a', for <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym> it reports '.mp3'. </td><td class="col2"> </td>
</tr>
<tr class="row4">
<td class="col0"> avcprofile </td><td class="col1 leftalign"> 66, 77, 88, 100, 110, 122 or 144 </td><td class="col2 leftalign"> Corresponds to the H.264 profiles </td>
</tr>
<tr class="row5">
<td class="col0"> avclevel </td><td class="col1 leftalign"> A number between 10 and 51. </td><td class="col2 leftalign"> Consult <a href="http://en.wikipedia.org/wiki/H264#Levels" class="urlextern" title="http://en.wikipedia.org/wiki/H264#Levels" rel="nofollow">this</a> list to find out more. </td>
</tr>
<tr class="row6">
<td class="col0"> aottype </td><td class="col1 leftalign"> Either 0, 1 or 2. </td><td class="col2 leftalign"> This corresponds to AAC Main, AAC LC and SBR audio types. </td>
</tr>
<tr class="row7">
<td class="col0"> moovposition </td><td class="col1 leftalign"> int </td><td class="col2 leftalign"> The offset in bytes of the <a href="http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf" class="urlextern" title="http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf" rel="nofollow">moov atom</a> in a file. </td>
</tr>
<tr class="row8">
<td class="col0"> trackinfo </td><td class="col1 leftalign"> Array </td><td class="col2 leftalign"> An array of objects containing various infomation about all the tracks in a file. </td>
</tr>
<tr class="row9">
<td class="col0"> chapters </td><td class="col1 leftalign"> Array </td><td class="col2 leftalign"> Information about chapters in audiobooks. </td>
</tr>
<tr class="row10">
<td class="col0"> seekpoints </td><td class="col1 leftalign"> Array </td><td class="col2 leftalign"> Times you can directly feed into NetStream.seek(); </td>
</tr>
<tr class="row11">
<td class="col0"> videoframerate </td><td class="col1 leftalign"> int </td><td class="col2 leftalign"> The frame rate of the video if a monotone frame rate is used. Most videos will have a monotone frame rate. </td>
</tr>
<tr class="row12">
<td class="col0"> audiosamplerate </td><td class="col1"> </td><td class="col2 leftalign"> The original sampling rate of the audio track. </td>
</tr>
<tr class="row13">
<td class="col0"> audiochannels </td><td class="col1"> </td><td class="col2 leftalign"> The original number of channels of the audio track. </td>
</tr>
<tr class="row14">
<td class="col0"> tags </td><td class="col1"> </td><td class="col2 leftalign"> ID3 like tag information </td>
</tr>
</tbody></table></div>
</div>
<div class="secedit editbutton_section editbutton_10"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[Metadata] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="10991-12281"><input type="submit" value="Edit" class="button" title="Metadata"></div></form></div>
<h2 class="sectionedit12"><a name="flv_format" id="flv_format">FLV Format</a></h2>
<div class="level2">
<p>
A Flash Video file (.FLV file extension) consists of a short header, and then interleaved audio, video, and metadata packets. The audio and video packets are stored very similarly to those in <a href="http://osflash.org/swf" class="wikilink1" title="swf">SWF</a>, and the metadata packets consist of <a href="http://osflash.org/documentation/amf" class="wikilink1" title="documentation:amf">AMF</a> data.
</p>
</div>
<h4><a name="flv_header" id="flv_header">FLV Header</a></h4>
<div class="level4">
<div class="table sectionedit13"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Field </th><th class="col1 leftalign"> Data Type </th><th class="col2 leftalign"> Example </th><th class="col3 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> Signature </td><td class="col1 leftalign"> byte[3] </td><td class="col2 leftalign"> “FLV” </td><td class="col3 leftalign"> Always “FLV” </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> Version </td><td class="col1 leftalign"> uint8 </td><td class="col2 leftalign"> “\x01” (1) </td><td class="col3 leftalign"> Currently 1 for known FLV files </td>
</tr>
<tr class="row3">
<td class="col0 leftalign"> Flags </td><td class="col1"> uint8 bitmask </td><td class="col2 leftalign"> “\x05” (5, audio+video) </td><td class="col3 leftalign"> Bitmask: 4 is audio, 1 is video </td>
</tr>
<tr class="row4">
<td class="col0 leftalign"> Offset </td><td class="col1 leftalign"> uint32_be </td><td class="col2 leftalign"> “\x00\x00\x00\x09” (9) </td><td class="col3 leftalign"> Total size of header (always 9 for known FLV files) </td>
</tr>
</tbody></table></div>
</div>
<h4><a name="flv_stream" id="flv_stream">FLV Stream</a></h4>
<div class="level4">
<div class="table sectionedit14"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Field </th><th class="col1 leftalign"> Data Type </th><th class="col2 leftalign"> Example </th><th class="col3 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> PreviousTagSize </td><td class="col1 leftalign"> uint32_be </td><td class="col2 leftalign"> “\x00\x00\x00\x00” (0) </td><td class="col3"> Always 0 </td>
</tr>
</tbody></table></div>
<p>
Then a sequence of tags <strong>followed</strong> by their size until <acronym title="End of file">EOF</acronym>.
</p>
</div>
<h4><a name="flv_tag" id="flv_tag">FLV Tag</a></h4>
<div class="level4">
<div class="table sectionedit15"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Field </th><th class="col1 leftalign"> Data Type </th><th class="col2 leftalign"> Example </th><th class="col3 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> Type </td><td class="col1 leftalign"> uint8 </td><td class="col2 leftalign"> “\x12” (0x12, META) </td><td class="col3 leftalign"> Determines the layout of Body, see below for tag types </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> BodyLength </td><td class="col1 leftalign"> uint24_be </td><td class="col2 leftalign"> “\x00\x00\xe0” (224) </td><td class="col3 leftalign"> Size of Body (total tag size - 11) </td>
</tr>
<tr class="row3">
<td class="col0 leftalign"> Timestamp </td><td class="col1 leftalign"> uint24_be </td><td class="col2 leftalign"> “\x00\x00\x00” (0) </td><td class="col3 leftalign"> Timestamp of tag (in milliseconds) </td>
</tr>
<tr class="row4">
<td class="col0 leftalign"> TimestampExtended </td><td class="col1 leftalign"> uint8 </td><td class="col2 leftalign"> “\x00” (0) </td><td class="col3 leftalign"> Timestamp extension to form a uint32_be. This field has the upper 8 bits. </td>
</tr>
<tr class="row5">
<td class="col0 leftalign"> StreamId </td><td class="col1 leftalign"> uint24_be </td><td class="col2 leftalign"> “\x00\x00\x00” (0) </td><td class="col3 leftalign"> Always 0 </td>
</tr>
<tr class="row6">
<td class="col0 leftalign"> Body </td><td class="col1 leftalign"> byte[BodyLength] </td><td class="col2 leftalign"></td><td class="col3 leftalign"> Dependent on the value of Type </td>
</tr>
</tbody></table></div>
</div>
<h4><a name="previous_tag_size" id="previous_tag_size">Previous tag size</a></h4>
<div class="level4">
<div class="table sectionedit16"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Field </th><th class="col1 leftalign"> Data Type </th><th class="col2 leftalign"> Example </th><th class="col3 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> PreviousTagSize </td><td class="col1 leftalign"> uint32_be </td><td class="col2 leftalign"> “\x00\x00\x00\x00” (0) </td><td class="col3"> Total size of previous tag, or 0 for first tag</td>
</tr>
</tbody></table></div>
</div>
<h4><a name="flv_tag_types" id="flv_tag_types">FLV Tag Types</a></h4>
<div class="level4">
<div class="table sectionedit17"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Tag code </th><th class="col1 leftalign"> Name </th><th class="col2 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> 0x08 </td><td class="col1 leftalign"> AUDIO </td><td class="col2 leftalign"> Contains an audio packet similar to a <a href="http://osflash.org/swf" class="wikilink1" title="swf">SWF</a> SoundStreamBlock plus codec information </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> 0x09 </td><td class="col1 leftalign"> VIDEO </td><td class="col2 leftalign"> Contains a video packet similar to a <a href="http://osflash.org/swf" class="wikilink1" title="swf">SWF</a> VideoFrame plus codec information </td>
</tr>
<tr class="row3">
<td class="col0 leftalign"> 0x12 </td><td class="col1 leftalign"> META </td><td class="col2 leftalign"> Contains two <a href="http://osflash.org/amf" class="wikilink2" title="amf" rel="nofollow">AMF</a> packets, the name of the event and the data to go with it </td>
</tr>
</tbody></table></div>
</div>
<h4><a name="flv_tag_0x08audio" id="flv_tag_0x08audio">FLV Tag 0x08: AUDIO</a></h4>
<div class="level4">
<p>
The first byte of an audio packet contains bitflags that
describe the codec used, with the following layout:
</p>
<div class="table sectionedit18"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Name </th><th class="col1 leftalign"> Expression </th><th class="col2 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> soundType </td><td class="col1 leftalign"> (byte &amp; 0x01) » 0 </td><td class="col2 leftalign"> 0: mono, 1: stereo </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> soundSize </td><td class="col1 leftalign"> (byte &amp; 0x02) » 1 </td><td class="col2 leftalign"> 0: 8-bit, 1: 16-bit </td>
</tr>
<tr class="row3">
<td class="col0 leftalign"> soundRate </td><td class="col1 leftalign"> (byte &amp; 0x0C) » 2 </td><td class="col2 leftalign"> 0: 5.5 kHz (or speex 16kHz), 1: 11 kHz, 2: 22 kHz, 3: 44 kHz </td>
</tr>
<tr class="row4">
<td class="col0 leftalign"> soundFormat </td><td class="col1 leftalign"> (byte &amp; 0xf0) » 4 </td><td class="col2 leftalign"> 0: Uncompressed, 1: ADPCM, 2: <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym>, 5: Nellymoser 8kHz mono, 6: Nellymoser, 11: Speex </td>
</tr>
</tbody></table></div>
<p>
The rest of the audio packet is simply the relevant data for that format, as per a <a href="http://osflash.org/swf" class="wikilink1" title="swf">SWF</a> SoundStreamBlock.
</p>
</div>
<h4><a name="flv_tag_0x09video" id="flv_tag_0x09video">FLV Tag 0x09: VIDEO</a></h4>
<div class="level4">
<p>
The first byte of a video packet describes contains bitflags
that describe the codec used, and the type of frame
</p>
<div class="table sectionedit19"><table class="inline">
<tbody><tr class="row0">
<th class="col0 leftalign"> Name </th><th class="col1 leftalign"> Expression </th><th class="col2 leftalign"> Description </th>
</tr>
<tr class="row1">
<td class="col0 leftalign"> codecID </td><td class="col1 leftalign"> (byte &amp; 0x0f) » 0 </td><td class="col2"> 2: Sorensen H.263, 3: Screen video, 4: On2 VP6, 5: On2 VP6 Alpha, 6: ScreenVideo 2 </td>
</tr>
<tr class="row2">
<td class="col0 leftalign"> frameType </td><td class="col1 leftalign"> (byte &amp; 0xf0) » 4 </td><td class="col2"> 1: keyframe, 2: inter frame, 3: disposable inter frame </td>
</tr>
</tbody></table></div>
<p>
In some cases it is also useful to decode some of the body of the video
packet, such as to acquire its resolution (if the initial onMetaData META
tag is missing, for example).
</p>
<p>
TODO: Describe the techniques for acquiring this information. Until then, you can
consult the <a href="http://osflash.org/flashticle" class="wikilink1" title="flashticle">flashticle</a> sources.
</p>
</div>
<h4><a name="flv_tag_0x12meta" id="flv_tag_0x12meta">FLV Tag 0x12: META</a></h4>
<div class="level4">
<p>
The contents of a meta packet are two <a href="http://osflash.org/amf" class="wikilink2" title="amf" rel="nofollow">AMF</a> packets. The first is
almost always a short uint16_be length-prefixed UTF-8 string
(<a href="http://osflash.org/amf" class="wikilink2" title="amf" rel="nofollow">AMF</a> type 0x02), and the second is typically a mixed array
(<a href="http://osflash.org/amf" class="wikilink2" title="amf" rel="nofollow">AMF</a> type 0x08). However, the second chunk typically contains
a variety of types, so a full <a href="http://osflash.org/amf" class="wikilink2" title="amf" rel="nofollow">AMF</a> parser should be used.
</p>
</div>
<div class="secedit editbutton_section editbutton_12"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[FLV Format] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="12282-16912"><input type="submit" value="Edit" class="button" title="FLV Format"></div></form></div>
<h2 class="sectionedit20"><a name="http_streaming" id="http_streaming">HTTP Streaming</a></h2>
<div class="level2">
<p>
It is possible to semi-stream flv over http using a trick which sends the normal headers then skips forward to a desired point in the file and moves the timestamps forward accordingly.
</p>
<p>
<a href="http://www.flashcomguru.com/index.cfm/2005/11/2/Streaming-flv-video-via-PHP-take-two" class="urlextern" title="http://www.flashcomguru.com/index.cfm/2005/11/2/Streaming-flv-video-via-PHP-take-two" rel="nofollow">A sample php script and fla is available at FlashComGuru</a>
</p>
<p>
Another tool that you can use to stream flv files using http is using <a href="http://fanno.dk/index.php?option=com_content&task=blogcategory&id=15&Itemid=53" class="urlextern" title="http://fanno.dk/index.php?option=com_content&amp;task=blogcategory&amp;id=15&amp;Itemid=53" rel="nofollow">Flv4PHP</a> this tool is both a FLV Metadata injector and a stream tool, using php 4.x. this Project is <acronym title="GNU General Public License">GPL</acronym>.
</p>
</div>
<div class="secedit editbutton_section editbutton_20"><form class="button btn_secedit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value="1322806619"><input type="hidden" name="summary" value="[HTTP Streaming] "><input type="hidden" name="target" value="section"><input type="hidden" name="range" value="16913-"><input type="submit" value="Edit" class="button" title="HTTP Streaming"></div></form></div><div class="footnotes">
<div class="fn"><sup><a href="http://osflash.org/flv#fnt__1" id="fn__1" name="fn__1" class="fn_bot">1)</a></sup>
The support of AAC allows you to encode audio to 64Kbit/s with the same quality of a 128Kbit/s encoded <acronym title="Motion Picture Experts Group Layer 3">MP3</acronym>. Further more, for other use more susceptible to bandwidth usage, like Internet Radio, HE-AAC v2 gives the possibility to encode audio to 32Kbit/s or lower with a surprisingly good final result. In low bitrate streaming scenarios this can make the difference.</div>
<div class="fn"><sup><a href="http://osflash.org/flv#fnt__2" id="fn__2" name="fn__2" class="fn_bot">2)</a></sup>
Flash documentation does not state a number for “their” version of Sorenson but describes the codec as a variant of <a href="http://www.itu.int/ITU-T/" class="urlextern" title="http://www.itu.int/ITU-T/" rel="nofollow">ITU-T</a> (International Telecommunications Union-Telecommunication Standardization Sector) recommendation <a href="http://en.wikipedia.org/wiki/H.263" class="urlextern" title="http://en.wikipedia.org/wiki/H.263" rel="nofollow">H.263</a> (<a href="http://www.digitalpreservation.gov/formats/fdd/fdd000080.shtml" class="urlextern" title="http://www.digitalpreservation.gov/formats/fdd/fdd000080.shtml" rel="nofollow">MPEG-4_V</a>). In early 2006, one of Sorenson's compression applications to produce content for Flash offered the <a href="http://www.digitalpreservation.gov/formats/fdd/fdd000066.shtml" class="urlextern" title="http://www.digitalpreservation.gov/formats/fdd/fdd000066.shtml" rel="nofollow">Sorenson_3</a> codec, described by experts as a variant of ITU-T H.264 (<a href="http://www.digitalpreservation.gov/formats/fdd/fdd000081.shtml" class="urlextern" title="http://www.digitalpreservation.gov/formats/fdd/fdd000081.shtml" rel="nofollow">MPEG-4_AVC</a>). By late 2006, Sorenson offered new compression applications with other outputs.</div>
<div class="fn"><sup><a href="http://osflash.org/flv#fnt__3" id="fn__3" name="fn__3" class="fn_bot">3)</a></sup>
This codec divides the screen in wide macroblocks (es: 64×64 pixels), reduces the number of colors, and transmits the changed blocks after compressing them in <a href="http://en.wikipedia.org/wiki/Zlib" class="urlextern" title="http://en.wikipedia.org/wiki/Zlib" rel="nofollow">zlib</a>. This is very similar to what VNC does.formats are bitmap tile based, can be lossy by reducing color depths and are compressed</div>
<div class="fn"><sup><a href="http://osflash.org/flv#fnt__4" id="fn__4" name="fn__4" class="fn_bot">4)</a></sup>
This codec can use two different types of macroblock: Iblock and Kblock. The Kblock works like a keyframe and is archived for future references. The Iblock is encoded as differences from a previous block. This new approach, similar to the usual compression of generic video content, guarantees a much better compression ratio, especially in a standard “moving windows” scenario.</div>
</div>
<div class="comment_wrapper">
<h2><a name="discussion__section" id="discussion__section">
Discussion
</a></h2>
<div class="level2 hfeed">
<div class="hentry">
<div class="comment_head">
<a name="comment_c8e7e062114b038b3efbe276e9b8b4a8" id="comment_c8e7e062114b038b3efbe276e9b8b4a8"></a>
<span class="vcard author"><span class="fn">WattsArlene</span></span>, <abbr class="published" title="2011-01-11T01:54:04Z">2011/01/11 01:54</abbr>
</div>
<div class="comment_body entry-content">
That's good that we can get the &lt;a href="http://bestfinance-blog.com/topics/personal-loans"&gt;personal loans&lt;/a&gt; moreover, this opens up completely new possibilities.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="c8e7e062114b038b3efbe276e9b8b4a8">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_d026b76350f7475da83b6992d895400f" id="comment_d026b76350f7475da83b6992d895400f"></a>
<span class="vcard author"><span class="fn">koisirinut</span></span>, <abbr class="published" title="2011-01-15T11:03:04Z">2011/01/15 11:03</abbr>
</div>
<div class="comment_body entry-content">
**Bold Text**
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="d026b76350f7475da83b6992d895400f">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_7a598a1b59df777722b3cb3b52553244" id="comment_7a598a1b59df777722b3cb3b52553244"></a>
<span class="vcard author"><span class="fn">muhammad basar</span></span>, <abbr class="published" title="2011-01-16T09:35:42Z">2011/01/16 09:35</abbr>
</div>
<div class="comment_body entry-content">
http://bestfinance-blog.com/topics/personal-loans"&gt;personal loans&lt;/a&gt; moreover, this opens up completely new possibilities.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="7a598a1b59df777722b3cb3b52553244">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_0b15e51164660e15d87f6a00d65aee7e" id="comment_0b15e51164660e15d87f6a00d65aee7e"></a>
<span class="vcard author"><span class="fn">Actarus</span></span>, <abbr class="published" title="2011-01-29T08:24:32Z">2011/01/29 08:24</abbr>
</div>
<div class="comment_body entry-content">
Great documentation! Now, the RIFF format should be documented as well to complete this jewel. I have benchmarked the flv format using the wonderful getID3 library, it's here: http://tinyurl.com/flvdump, Enjoy.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="0b15e51164660e15d87f6a00d65aee7e">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_4dde8068e4a8eaab434aa572d59a7dc3" id="comment_4dde8068e4a8eaab434aa572d59a7dc3"></a>
<span class="vcard author"><span class="fn">khan</span></span>, <abbr class="published" title="2011-02-22T08:40:33Z">2011/02/22 08:40</abbr>
</div>
<div class="comment_body entry-content">
**Bold Text**
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="4dde8068e4a8eaab434aa572d59a7dc3">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_b2176092ebf84736071e7e1cf8ca1757" id="comment_b2176092ebf84736071e7e1cf8ca1757"></a>
<span class="vcard author"><span class="fn">mortgage loans</span></span>, <abbr class="published" title="2011-06-02T17:16:08Z">2011/06/02 17:16</abbr>
</div>
<div class="comment_body entry-content">
Some time before, I really needed to buy a good car for my corporation but I did not have enough money and could not buy anything. Thank heaven my colleague suggested to try to take the credit loans at trustworthy creditors. Hence, I acted that and was satisfied with my consolidation loan.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="b2176092ebf84736071e7e1cf8ca1757">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_ae70f74eec88f9786d641b67e36d2e9c" id="comment_ae70f74eec88f9786d641b67e36d2e9c"></a>
<span class="vcard author"><span class="fn">loans</span></span>, <abbr class="published" title="2011-06-29T04:15:09Z">2011/06/29 04:15</abbr>
</div>
<div class="comment_body entry-content">
The loan suppose to be important for people, which want to start their own organization. In fact, it's very comfortable to get a student loan.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="ae70f74eec88f9786d641b67e36d2e9c">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_82e88e7e53b1128d7dc753bffa698b50" id="comment_82e88e7e53b1128d7dc753bffa698b50"></a>
<span class="vcard author"><span class="fn">home loans</span></span>, <abbr class="published" title="2011-07-13T23:30:11Z">2011/07/13 23:30</abbr>
</div>
<div class="comment_body entry-content">
Every one acknowledges that men's life seems to be high priced, nevertheless people require cash for various issues and not every person gets big sums money. Hence to get fast mortgage loans and credit loan would be a correct solution.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="82e88e7e53b1128d7dc753bffa698b50">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_8ac40edc198d913f7c2ce450ff90f978" id="comment_8ac40edc198d913f7c2ce450ff90f978"></a>
<span class="vcard author"><span class="fn">johncein</span></span>, <abbr class="published" title="2011-07-16T02:06:04Z">2011/07/16 02:06</abbr>
</div>
<div class="comment_body entry-content">
informative read... thanks for the source.<br><br><br><br>&lt;a href="http://hdwebplayer.com"&gt;Flv Player&lt;/a&gt;
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="8ac40edc198d913f7c2ce450ff90f978">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_df5e7e76303096d545f8f7dc92c0568e" id="comment_df5e7e76303096d545f8f7dc92c0568e"></a>
<span class="vcard author"><span class="fn">valerie</span></span>, <abbr class="published" title="2011-08-27T02:00:07Z">2011/08/27 02:00</abbr>
</div>
<div class="comment_body entry-content">
Eben pagan has released his new course guru blueprint and in this guru masterclass he teaches all that he has learn in his marketing career. <br>Check this website to know more about Eben pagan guru Master class..&lt;a href=&gt;]Eben pagan guru blueprint&lt;/a&gt; <br>If you want to know more about the course you can follow the video on youtube about the guru blueprint.. <br>&lt;a href=http://www.youtube.com/watch?v=rm8Spt2_Zv0&gt;Eben pagan guru blueprint&lt;/a&gt; <br>&lt;a href=http://www.youtube.com/watch?v=5MrCM4MnSqM&gt;Eben pagan guru blueprint&lt;/a&gt; <br>&lt;a href=http://www.youtube.com/watch?v=ZEYhOkb9Wys&gt;Eben pagan guru blueprint&lt;/a&gt; <br> <br>you can go here to find out more about the guru masterclass.. &lt;a href=http://www.helpandinfo.com/guru-masterclass-free-training-video-three.html&gt;Eben pagan guru blueprint&lt;/a&gt; <br> <br> <br> <br>You can learn much more about marketing by just listening to this guy talk. he is such an amazing personality. See as eben pagan releases his master class.. <br>guru blueprint..
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="df5e7e76303096d545f8f7dc92c0568e">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_3f6f7ace43a8a97e126a4760a70f1d18" id="comment_3f6f7ace43a8a97e126a4760a70f1d18"></a>
<span class="vcard author"><span class="fn">loans</span></span>, <abbr class="published" title="2011-09-01T17:28:20Z">2011/09/01 17:28</abbr>
</div>
<div class="comment_body entry-content">
People in the world take the mortgage loans from various creditors, because that is easy.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="3f6f7ace43a8a97e126a4760a70f1d18">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_4ecb80aacb60a22b14e83c5f40c92eb5" id="comment_4ecb80aacb60a22b14e83c5f40c92eb5"></a>
<span class="vcard author"><span class="fn">business loans</span></span>, <abbr class="published" title="2011-09-20T11:06:11Z">2011/09/20 11:06</abbr>
</div>
<div class="comment_body entry-content">
This is known that money can make people independent. But how to act if someone doesn't have cash? The one way only is to get the mortgage loans or just credit loan.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="4ecb80aacb60a22b14e83c5f40c92eb5">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_63b8e3b6fba6a5e91a7f991aa4b096a4" id="comment_63b8e3b6fba6a5e91a7f991aa4b096a4"></a>
<span class="vcard author"><span class="fn">confused</span></span>, <abbr class="published" title="2011-10-13T18:15:45Z">2011/10/13 18:15</abbr>
</div>
<div class="comment_body entry-content">
WHAT THE HELL ARE DUMB ASS BOTS DOING ON HERE!!! NOBODY WANTS YOUR SCAMS OR ANY OTHER HORSE SHIT YOU CAN SHOVEL, GET A FUCKING LIFE.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="63b8e3b6fba6a5e91a7f991aa4b096a4">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_18022d31dfd0ae557e1f79a33ec4030e" id="comment_18022d31dfd0ae557e1f79a33ec4030e"></a>
<span class="vcard author"><span class="fn">gymnsmitift</span></span>, <abbr class="published" title="2011-11-22T18:38:54Z">2011/11/22 18:38</abbr>
</div>
<div class="comment_body entry-content">
wow, great forum! &lt;a href=https://wiki.citizen.apps.gov/NEA_OPI/index.php/About_Antennadeals.com&gt;Antennadeals.com&lt;/a&gt;?
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="18022d31dfd0ae557e1f79a33ec4030e">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_3ee3d4d3b9f6057651bb4bed46d83939" id="comment_3ee3d4d3b9f6057651bb4bed46d83939"></a>
<span class="vcard author"><span class="fn">Postupalka</span></span>, <abbr class="published" title="2011-12-06T15:38:43Z">2011/12/06 15:38</abbr>
</div>
<div class="comment_body entry-content">
Прокси-сервер работает на 8080 &lt;a href="http://avtomast.com/ceni_na_toplivo-3.html"&gt;http://avtomast.com/&lt;/a&gt; каневской чат
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="3ee3d4d3b9f6057651bb4bed46d83939">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="hentry">
<div class="comment_head">
<a name="comment_25cd8133e922601184904567403e60ed" id="comment_25cd8133e922601184904567403e60ed"></a>
<span class="vcard author"><span class="fn">Ali</span></span>, <abbr class="published" title="2012-01-02T07:38:45Z">2012/01/02 07:38</abbr>
</div>
<div class="comment_body entry-content">
**Bold Text**Hello<br>I am working on a project in Flash which the user can draw some animation and then covert the final product as an FLV file so he can share it on facebook and youtube,<br>I have searched for a suitable solution but yet cant find any, in go Animat (www.goAnimat.com) engine covert to FLV very smoothly,<br>So is it possible to guide me on how to do this, or maybe provide my with this service on servers.<br>I would really appreciate you help on this.
</div>
<div class="comment_buttons">
<form class="button discussion__reply" method="get" action="http://osflash.org/doku.php#discussion__comment_form">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="reply">
<input type="hidden" name="cid" value="25cd8133e922601184904567403e60ed">
<input type="submit" value="Reply" class="button" title="Reply">
</div>
</form>
</div>
</div>
<div class="comment_form">
<form id="discussion__comment_form" method="post" action="http://osflash.org/doku.php" accept-charset="utf-8">
<div class="no">
<input type="hidden" name="id" value="flv">
<input type="hidden" name="do" value="show">
<input type="hidden" name="comment" value="add">
<input type="hidden" name="reply" value="">
<input type="hidden" name="user" value="80.68.252.79,10.31.1.141">
<div class="comment_name">
<label class="block" for="discussion__comment_name">
<span>Real name:</span>
<input type="text" class="edit" name="name" id="discussion__comment_name" size="50" tabindex="1" value="">
</label>
</div>
<div class="comment_mail">
<label class="block" for="discussion__comment_mail">
<span>E-Mail:</span>
<input type="text" class="edit" name="mail" id="discussion__comment_mail" size="50" tabindex="2" value="">
</label>
</div>
<div class="comment_text">
<div id="discussion__comment_toolbar"><button class="toolbutton" title="Bold Text [B]" accesskey="b"><img src="./flv_files/bold.png"></button><button class="toolbutton" title="Italic Text [I]" accesskey="i"><img src="./flv_files/italic.png"></button><button class="toolbutton" title="Underlined Text [U]" accesskey="u"><img src="./flv_files/underline.png"></button><button class="toolbutton" title="Code Text [C]" accesskey="c"><img src="./flv_files/mono.png"></button><button class="toolbutton" title="Strike-through Text [D]" accesskey="d"><img src="./flv_files/strike.png"></button><button class="toolbutton" title="Same Level Headline [8]" accesskey="8"><img src="./flv_files/hequal.png"></button><button class="toolbutton" title="Lower Headline [9]" accesskey="9"><img src="./flv_files/hminus.png"></button><button class="toolbutton" title="Higher Headline [0]" accesskey="0"><img src="./flv_files/hplus.png"></button><button class="toolbutton pk_hl" title="Select Headline"><img src="./flv_files/h.png"></button></div>
<textarea class="edit" name="text" cols="80" rows="10" id="discussion__comment_text" tabindex="5"></textarea>
</div>
<div style="width: 320px;"></div><script type="text/javascript">
var RecaptchaOptions = {theme: 'white',lang: 'en'
};
</script><script type="text/javascript" src="./flv_files/challenge"></script><script type="text/javascript" src="./flv_files/recaptcha.js"></script><div id="recaptcha_widget_div" style="" class=" recaptcha_nothad_incorrect_sol recaptcha_isnot_showing_audio"><div id="recaptcha_area"><table id="recaptcha_table" class="recaptchatable recaptcha_theme_white"> <tbody><tr> <td colspan="6" class="recaptcha_r1_c1"></td> </tr> <tr> <td class="recaptcha_r2_c1"></td> <td colspan="4" class="recaptcha_image_cell"><div id="recaptcha_image" style="width: 300px; height: 57px; "><img style="display:block;" alt="Проверка по слову reCAPTCHA" height="57" width="300" src="./flv_files/image"></div></td> <td class="recaptcha_r2_c2"></td> </tr> <tr> <td rowspan="6" class="recaptcha_r3_c1"></td> <td colspan="4" class="recaptcha_r3_c2"></td> <td rowspan="6" class="recaptcha_r3_c3"></td> </tr> <tr> <td rowspan="3" class="recaptcha_r4_c1" height="49"> <div class="recaptcha_input_area"> <label for="recaptcha_response_field" class="recaptcha_input_area_text"><span id="recaptcha_instructions_image" class="recaptcha_only_if_image recaptcha_only_if_no_incorrect_sol">Введите то, что видите:</span><span id="recaptcha_instructions_audio" class="recaptcha_only_if_no_incorrect_sol recaptcha_only_if_audio">Введите то, что слышите:</span><span id="recaptcha_instructions_error" class="recaptcha_only_if_incorrect_sol">Неправильно. Повторите попытку.</span></label><br> <span id="recaptcha_challenge_field_holder" style="display: none; "><input type="hidden" name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_Vut1HzJuqKt7EvDt-hY-WMA3VOT3S06e-i7HAnJ_qqXzgUYoH27KMjCNNzRnuntYAjDB1M6qaZ3wQYeumJpisKnJgNZou7KtjPUYjT242OihFfzGNtDszqkcaSVDVmSGR9BROuthp9KbCGj6BCzfSIvrnDs1ow"></span><input name="recaptcha_response_field" id="recaptcha_response_field" type="text" autocorrect="off" autocapitalize="off" autocomplete="off"> </div> </td> <td rowspan="4" class="recaptcha_r4_c2"></td> <td><a id="recaptcha_reload_btn" title="Обновить" href="javascript:Recaptcha.reload();"><img id="recaptcha_reload" width="25" height="17" src="./flv_files/refresh.gif" alt="Обновить"></a></td> <td rowspan="4" class="recaptcha_r4_c4"></td> </tr> <tr> <td><a id="recaptcha_switch_audio_btn" class="recaptcha_only_if_image" title="Звуковая проверка" href="javascript:Recaptcha.switch_type('audio');"><img id="recaptcha_switch_audio" width="25" height="16" alt="Звуковая проверка" src="./flv_files/audio.gif"></a><a id="recaptcha_switch_img_btn" class="recaptcha_only_if_audio" title="Визуальная проверка" href="javascript:Recaptcha.switch_type('image');"><img id="recaptcha_switch_img" width="25" height="16" alt="Визуальная проверка" src="./flv_files/text.gif"></a></td> </tr> <tr> <td><a id="recaptcha_whatsthis_btn" title="Справка" href="http://www.google.com/recaptcha/help?c=03AHJ_Vut1HzJuqKt7EvDt-hY-WMA3VOT3S06e-i7HAnJ_qqXzgUYoH27KMjCNNzRnuntYAjDB1M6qaZ3wQYeumJpisKnJgNZou7KtjPUYjT242OihFfzGNtDszqkcaSVDVmSGR9BROuthp9KbCGj6BCzfSIvrnDs1ow&hl=ru" target="_blank"><img id="recaptcha_whatsthis" width="25" height="16" src="./flv_files/help.gif" alt="Справка"></a></td> </tr> <tr> <td class="recaptcha_r7_c1"></td> <td class="recaptcha_r8_c1"></td> </tr> </tbody></table> </div></div><script>Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();</script>
<noscript>
&lt;iframe src="http://api.recaptcha.net/noscript?k=6LdTL8ASAAAAANsSpVQoKQNotApGWtkt72So2PCS" height="300" width="500" frameborder="0"&gt;&lt;/iframe&gt;&lt;br/&gt;
&lt;textarea name="recaptcha_challenge_field" rows="3" cols="40"&gt;&lt;/textarea&gt;
&lt;input type="hidden" name="recaptcha_response_field" value="manual_challenge"/&gt;
</noscript> <input class="button comment_submit" id="discussion__btn_submit" type="submit" name="submit" accesskey="s" value="Save" title="Save [S]" tabindex="7">
<input class="button comment_preview_button" id="discussion__btn_preview" type="button" name="preview" accesskey="p" value="Preview" title="Preview [P]">
<div class="comment_subscribe">
<input type="checkbox" id="discussion__comment_subscribe" name="subscribe" tabindex="6">
<label class="block" for="discussion__comment_subscribe">
<span>Subscribe to comments</span>
</label>
</div>
<div class="clearer"></div>
<div id="discussion__comment_preview">&nbsp;</div>
</div>
</form>
</div>
</div>
</div>
<!-- wikipage stop -->
</div>
<div class="clearer">&nbsp;</div>
<div class="stylefoot">
<div class="meta">
<div class="user">
</div>
<div class="doc">
flv.txt · Last modified: 2011/12/02 01:16 by 219.161.44.239 </div>
</div>
<div class="bar" id="bar__bottom">
<div class="bar-left" id="bar__bottomleft">
<form class="button btn_edit" method="post" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="edit"><input type="hidden" name="rev" value=""><input type="submit" value="Edit this page" class="button" accesskey="e" title="Edit this page [E]"></div></form> <form class="button btn_revs" method="get" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="revisions"><input type="submit" value="Old revisions" class="button" accesskey="o" title="Old revisions [O]"></div></form> </div>
<div class="bar-right" id="bar__bottomright">
<form class="button btn_login" method="get" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="login"><input type="hidden" name="sectok" value="a9d499d104bcfce8bd4f08e6bf64edd2"><input type="submit" value="Login" class="button" title="Login"></div></form> <form class="button btn_index" method="get" action="./flv_files/flv.html"><div class="no"><input type="hidden" name="do" value="index"><input type="submit" value="Sitemap" class="button" accesskey="x" title="Sitemap [X]"></div></form> <a class="nolink" href="http://osflash.org/flv#dokuwiki__top"><input type="button" class="button" value="Back to top" onclick="window.scrollTo(0, 0)" title="Back to top"></a>&nbsp;
</div>
<div class="clearer"></div>
</div>
</div>
</div><iframe src="about:blank" style="height: 0px; width: 0px; visibility: hidden; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; border-image: initial; ">This frame prevents back/forward cache problems in Safari.</iframe>
<div class="footerinc">
<a href="http://osflash.org/feed.php" title="Recent changes RSS feed"><img src="./flv_files/button-rss.png" width="80" height="15" alt="Recent changes RSS feed"></a>
<a href="http://www.dokuwiki.org/donate" title="Donate"><img src="./flv_files/button-donate.gif" alt="Donate" width="80" height="15"></a>
<a href="http://www.php.net/" title="Powered by PHP"><img src="./flv_files/button-php.gif" width="80" height="15" alt="Powered by PHP"></a>
<a href="http://validator.w3.org/check/referer" title="Valid XHTML 1.0"><img src="./flv_files/button-xhtml.png" width="80" height="15" alt="Valid XHTML 1.0"></a>
<a href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3" title="Valid CSS"><img src="./flv_files/button-css.png" width="80" height="15" alt="Valid CSS"></a>
<a href="http://dokuwiki.org/" title="Driven by DokuWiki"><img src="./flv_files/button-dw.png" width="80" height="15" alt="Driven by DokuWiki"></a>
</div>
<div class="no"><img src="./flv_files/indexer.php" width="1" height="1" alt=""></div>
<div class="picker pk_hl" id="picker0" style="position: absolute; margin-left: -10000px; margin-top: -10000px; "><button class="toolbutton" title="Level 1 Headline [1]" accesskey="1"><img src="./flv_files/h1.png"></button><button class="toolbutton" title="Level 2 Headline [2]" accesskey="2"><img src="./flv_files/h2.png"></button><button class="toolbutton" title="Level 3 Headline [3]" accesskey="3"><img src="./flv_files/h3.png"></button><button class="toolbutton" title="Level 4 Headline [4]" accesskey="4"><img src="./flv_files/h4.png"></button><button class="toolbutton" title="Level 5 Headline [5]" accesskey="5"><img src="./flv_files/h5.png"></button></div></body></html>

View file

@ -272,7 +272,7 @@ ngx_rtmp_init_events(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
}
}
if (ngx_array_init(&cmcf->calls, cf->pool, 1,
if (ngx_array_init(&cmcf->amf0, cf->pool, 1,
sizeof(ngx_hash_key_t)) != NGX_OK)
{
return NGX_ERROR;
@ -288,6 +288,42 @@ ngx_rtmp_init_events(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
return NGX_OK;
}
/*
static ngx_int_t
ngx_rtmp_init_amf0_handler(ngx_rtmp_core_main_conf_t *cmcf,
ngx_int_t id, ngx_array_t *array, ngx_hash_t *hash,
ngx_rtmp_event_handler_pt handler)
{
ngx_hash_init_t calls_hash;
ngx_rtmp_event_handler_pt *eh;
ngx_hash_key_t *h;
size_t n;
eh = ngx_array_push(&cmcf->events[id]);
*eh = handler;
h = array->elts;
for(n = 0; n < array->nelts; ++n, ++h) {
h->key_hash = ngx_hash_key_lc(h->key.data, h->key.len);
}
calls_hash.hash = hash;
calls_hash.key = ngx_hash_key_lc;
calls_hash.max_size = 512;
calls_hash.bucket_size = ngx_cacheline_size;
calls_hash.name = "amf0_hash";
calls_hash.pool = cf->pool;
calls_hash.temp_pool = NULL;
if (ngx_hash_init(&calls_hash, array->elts, array->nelts)
!= NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}
*/
static ngx_int_t
ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
@ -296,6 +332,7 @@ ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
ngx_rtmp_event_handler_pt *eh;
ngx_hash_key_t *h;
size_t n;
static size_t pm_events[] = {
NGX_RTMP_MSG_CHUNK_SIZE,
NGX_RTMP_MSG_ABORT,
@ -303,6 +340,11 @@ ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
NGX_RTMP_MSG_ACK_SIZE,
NGX_RTMP_MSG_BANDWIDTH
};
static size_t amf0_events[] = {
NGX_RTMP_MSG_AMF0_META,
NGX_RTMP_MSG_AMF0_SHARED,
NGX_RTMP_MSG_AMF0_CMD
};
/* init events */
for(n = 0; n < sizeof(pm_events) / sizeof(pm_events[0]); ++n) {
@ -310,19 +352,20 @@ ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
*eh = ngx_rtmp_protocol_message_handler;
}
for(n = 0; n < sizeof(amf0_events) / sizeof(amf0_events[0]); ++n) {
eh = ngx_array_push(&cmcf->events[amf0_events[n]]);
*eh = ngx_rtmp_amf0_message_handler;
}
eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_USER]);
*eh = ngx_rtmp_user_message_handler;
eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AMF0_CMD]);
*eh = ngx_rtmp_amf0_message_handler;
/* init calls */
h = cmcf->calls.elts;
for(n = 0; n < cmcf->calls.nelts; ++n, ++h) {
h = cmcf->amf0.elts;
for(n = 0; n < cmcf->amf0.nelts; ++n, ++h) {
h->key_hash = ngx_hash_key_lc(h->key.data, h->key.len);
}
calls_hash.hash = &cmcf->calls_hash;
calls_hash.hash = &cmcf->amf0_hash;
calls_hash.key = ngx_hash_key_lc;
calls_hash.max_size = 512;
calls_hash.bucket_size = ngx_cacheline_size;
@ -330,7 +373,7 @@ ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf)
calls_hash.pool = cf->pool;
calls_hash.temp_pool = NULL;
if (ngx_hash_init(&calls_hash, cmcf->calls.elts, cmcf->calls.nelts)
if (ngx_hash_init(&calls_hash, cmcf->amf0.elts, cmcf->amf0.nelts)
!= NGX_OK)
{
return NGX_ERROR;

View file

@ -158,7 +158,7 @@ typedef struct {
} ngx_rtmp_header_t;
typedef struct ngx_rtmp_stream_t {
typedef struct {
ngx_rtmp_header_t hdr;
uint32_t len; /* current fragment length */
ngx_chain_t *in;
@ -201,8 +201,6 @@ typedef struct ngx_rtmp_session_s {
typedef ngx_int_t (*ngx_rtmp_event_handler_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
typedef ngx_int_t (*ngx_rtmp_call_handler_pt)(ngx_rtmp_session_t *s,
double trans, ngx_chain_t *in);
typedef ngx_int_t (*ngx_rtmp_disconnect_handler_pt)(ngx_rtmp_session_t *s);
@ -211,8 +209,10 @@ typedef struct {
ngx_array_t listen; /* ngx_rtmp_listen_t */
ngx_array_t events[NGX_RTMP_MSG_MAX];
ngx_hash_t calls_hash;
ngx_array_t calls;
ngx_hash_t amf0_hash;
ngx_array_t amf0;
ngx_array_t disconnect;
} ngx_rtmp_core_main_conf_t;
@ -275,6 +275,11 @@ typedef struct {
((ngx_rtmp_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
#ifdef NGX_DEBUG
char* ngx_rtmp_message_type(uint8_t type);
char* ngx_rtmp_user_message_type(uint16_t evt);
#endif
void ngx_rtmp_init_connection(ngx_connection_t *c);
void ngx_rtmp_close_connection(ngx_connection_t *c);
u_char * ngx_rtmp_log_error(ngx_log_t *log, u_char *buf, size_t len);
@ -291,10 +296,14 @@ ngx_int_t ngx_rtmp_amf0_message_handler(ngx_rtmp_session_t *s,
/* Sending messages */
ngx_chain_t * ngx_rtmp_alloc_shared_buf(ngx_rtmp_session_t *s);
ngx_int_t ngx_rtmp_release_shared_buf(ngx_rtmp_session_t *s,
ngx_chain_t * ngx_rtmp_append_shared_bufs(ngx_rtmp_session_t *s,
ngx_chain_t *out, ngx_chain_t *in);
ngx_int_t ngx_rtmp_addref_shared_bufs(ngx_chain_t *in);
ngx_int_t ngx_rtmp_free_shared_buf(ngx_rtmp_session_t *s,
ngx_chain_t *out);
void ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *out, uint8_t fmt);
ngx_rtmp_header_t *lh, ngx_chain_t *out);
ngx_int_t ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out);
#define NGX_RTMP_LIMIT_SOFT 0
@ -330,8 +339,7 @@ ngx_int_t ngx_rtmp_send_user_ping_response(ngx_rtmp_session_t *s,
uint32_t timestamp);
/* AMF0 sender/receiver */
ngx_int_t ngx_rtmp_send_amf0(ngx_rtmp_session_t *s,
uint32_t csid, uint32_t msid,
ngx_int_t ngx_rtmp_send_amf0(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_amf0_elt_t *elts, size_t nelts);
ngx_int_t ngx_rtmp_receive_amf0(ngx_rtmp_session_t *s, ngx_chain_t *in,
ngx_rtmp_amf0_elt_t *elts, size_t nelts);

View file

@ -223,7 +223,8 @@ ngx_rtmp_amf0_read_object(ngx_rtmp_amf0_ctx_t *ctx, ngx_rtmp_amf0_elt_t *elts,
#define NGX_RTMP_AMF0_TILL_END_FLAG ((size_t)1 << (sizeof(size_t) * 8 - 1))
ngx_int_t
ngx_rtmp_amf0_read(ngx_rtmp_amf0_ctx_t *ctx, ngx_rtmp_amf0_elt_t *elts, size_t nelts)
ngx_rtmp_amf0_read(ngx_rtmp_amf0_ctx_t *ctx, ngx_rtmp_amf0_elt_t *elts,
size_t nelts)
{
void *data;
uint8_t type;

View file

@ -14,20 +14,22 @@ static char * ngx_rtmp_broadcast_merge_srv_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in);
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_create_stream(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in);
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in);
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in);
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_set_data_frame(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in);
ngx_rtmp_header_t *h, ngx_chain_t *in);
typedef struct {
ngx_str_t name;
ngx_rtmp_call_handler_pt handler;
ngx_rtmp_event_handler_pt handler;
} ngx_rtmp_broadcast_map_t;
@ -36,6 +38,7 @@ static ngx_rtmp_broadcast_map_t ngx_rtmp_broadcast_map[] = {
{ ngx_string("createStream"), ngx_rtmp_broadcast_create_stream },
{ ngx_string("publish"), ngx_rtmp_broadcast_publish },
{ ngx_string("play"), ngx_rtmp_broadcast_play },
{ ngx_string("@setDataFrame"), ngx_rtmp_broadcast_set_data_frame },
{ ngx_string("releaseStream"), ngx_rtmp_broadcast_ok },
{ ngx_string("FCPublish"), ngx_rtmp_broadcast_ok },
{ ngx_string("FCSubscribe"), ngx_rtmp_broadcast_ok },
@ -91,14 +94,17 @@ ngx_module_t ngx_rtmp_broadcast_module = {
#define NGX_RTMP_BROADCAST_PUBLISHER 0x01
#define NGX_RTMP_BROADCAST_SUBSCRIBER 0x02
#define NGX_RTMP_BROADCAST_WANT_KEYFRAME 0x04
#define NGX_RTMP_BROADCAST_DATA_FRAME 0x08
typedef struct ngx_rtmp_broadcast_ctx_s {
ngx_str_t stream;
ngx_rtmp_session_t *session;
struct ngx_rtmp_broadcast_ctx_s *next;
ngx_uint_t flags; /* publisher/subscriber */
ngx_uint_t flags; /* publisher/subscriber */
uint32_t csid;
ngx_rtmp_header_t lh; /* last a/v header */
ngx_chain_t *data_frame;
} ngx_rtmp_broadcast_ctx_t;
@ -242,20 +248,14 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
{
ngx_connection_t *c;
ngx_rtmp_broadcast_ctx_t *ctx, *cctx;
ngx_chain_t *out, *l, **ll;
u_char *p;
size_t nsubs, size;
ngx_chain_t *out;
size_t nsubs;
ngx_int_t vftype;
c = s->connection;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_broadcast_module);
/*
h->timestamp -= s->peer_epoch;
h->timestamp += s->epoch;
*/
if (ctx == NULL
|| !(ctx->flags & NGX_RTMP_BROADCAST_PUBLISHER))
{
@ -273,39 +273,9 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
vftype = ngx_rtmp_get_video_frame_type(in);
}
/* copy data to output stream */
out = NULL;
ll = &out;
p = in->buf->pos;
out = ngx_rtmp_append_shared_bufs(s, NULL, in);
for ( ;; ) {
l = ngx_rtmp_alloc_shared_buf(s);
if (l == NULL || l->buf == NULL) {
return NGX_ERROR;
}
*ll = l;
ll = &l->next;
while (l->buf->end - l->buf->last >= in->buf->last - p) {
l->buf->last = ngx_cpymem(l->buf->last, p,
in->buf->last - p);
in = in->next;
if (in == NULL) {
goto done;
}
p = in->buf->pos;
}
size = l->buf->end - l->buf->last;
l->buf->last = ngx_cpymem(l->buf->last, p, size);
p += size;
}
done:
*ll = NULL;
ngx_rtmp_prepare_message(s, h, out, 0/*fmt*/);
ngx_rtmp_prepare_message(s, h, &ctx->lh, out);
/* broadcast to all subscribers */
nsubs = 0;
@ -318,6 +288,24 @@ done:
&& !ngx_strncmp(cctx->stream.data, ctx->stream.data,
ctx->stream.len))
{
/* if we have metadata check if the subscriber
* has already received one */
if (ctx->data_frame
&& !(cctx->flags & NGX_RTMP_BROADCAST_DATA_FRAME))
{
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"sending data_frame");
if (ngx_rtmp_send_message(cctx->session, ctx->data_frame)
!= NGX_OK)
{
return NGX_ERROR;
}
cctx->flags |= NGX_RTMP_BROADCAST_DATA_FRAME;
}
/* is the subscriber waiting for
* a key frame? */
if (h->type == NGX_RTMP_MSG_VIDEO
&& cctx->flags & NGX_RTMP_BROADCAST_WANT_KEYFRAME)
{
@ -326,6 +314,7 @@ done:
}
cctx->flags &= ~NGX_RTMP_BROADCAST_WANT_KEYFRAME;
}
if (ngx_rtmp_send_message(cctx->session, out) != NGX_OK) {
return NGX_ERROR;
}
@ -333,9 +322,11 @@ done:
}
}
/* TODO: implement proper (refcount-based) buffer deletion */
/* no one subscriber? */
if (!nsubs
&& ngx_rtmp_release_shared_buf(s, out) != NGX_OK)
&& ngx_rtmp_free_shared_buf(s, out) != NGX_OK)
{
return NGX_ERROR;
}
@ -345,7 +336,7 @@ done:
static ngx_int_t
ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
@ -369,6 +360,7 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
};
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
{ NGX_RTMP_AMF0_OBJECT, NULL, in_cmd, sizeof(in_cmd) },
};
@ -387,7 +379,6 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
trans = in_trans;
ngx_str_set(&out_inf[0], "NetConnection.Connect.Success");
ngx_str_set(&out_inf[1], "status");
ngx_str_set(&out_inf[2], "Connection succeeded.");
@ -409,7 +400,7 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
return ngx_rtmp_send_ack_size(s, cscf->ack_window)
|| ngx_rtmp_send_bandwidth(s, cscf->ack_window, NGX_RTMP_LIMIT_SOFT)
|| ngx_rtmp_send_user_stream_begin(s, 0)
|| ngx_rtmp_send_amf0(s, 3, 0, out_elts,
|| ngx_rtmp_send_amf0(s, h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]))
? NGX_ERROR
: NGX_OK;
@ -417,12 +408,16 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
static ngx_int_t
ngx_rtmp_broadcast_create_stream(ngx_rtmp_session_t *s, double in_trans,
ngx_rtmp_broadcast_create_stream(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
static double trans;
static double stream;
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
};
static ngx_rtmp_amf0_elt_t out_elts[] = {
{ NGX_RTMP_AMF0_STRING, NULL, "_result", sizeof("_result") - 1 },
{ NGX_RTMP_AMF0_NUMBER, NULL, &trans, sizeof(trans) },
@ -433,18 +428,25 @@ ngx_rtmp_broadcast_create_stream(ngx_rtmp_session_t *s, double in_trans,
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"createStream() called");
trans = in_trans;
if (ngx_rtmp_receive_amf0(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
stream = 1;
return ngx_rtmp_send_amf0(s, 3, 0, out_elts,
return ngx_rtmp_send_amf0(s, h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
}
static ngx_int_t
ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, double in_trans,
ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_header_t sh;
static double trans;
static u_char pub_name[1024];
static u_char pub_type[1024];
@ -456,6 +458,7 @@ ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, double in_trans,
};
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
{ NGX_RTMP_AMF0_NULL, NULL, NULL, 0 },
{ NGX_RTMP_AMF0_STRING, NULL, pub_name, sizeof(pub_name) },
{ NGX_RTMP_AMF0_STRING, NULL, pub_type, sizeof(pub_type) },
@ -468,7 +471,6 @@ ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, double in_trans,
{ NGX_RTMP_AMF0_OBJECT, NULL, out_inf, sizeof(out_inf) },
};
if (ngx_rtmp_receive_amf0(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
@ -479,14 +481,22 @@ ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, double in_trans,
"publish() called; pubName='%s' pubType='%s'",
pub_name, pub_type);
if (ngx_rtmp_send_user_stream_begin(s, 1) != NGX_OK) {
return NGX_ERROR;
}
ngx_rtmp_broadcast_set_flags(s, NGX_RTMP_BROADCAST_PUBLISHER);
trans = in_trans;
ngx_str_set(&out_inf[0], "NetStream.Publish.Start");
ngx_str_set(&out_inf[1], "status");
ngx_str_set(&out_inf[2], "Publish succeeded.");
if (ngx_rtmp_send_amf0(s, 3, 0, out_elts,
memset(&sh, 0, sizeof(sh));
sh.type = NGX_RTMP_MSG_AMF0_CMD;
sh.csid = 5; /*FIXME*/
sh.msid = h->msid;
if (ngx_rtmp_send_amf0(s, &sh, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
{
return NGX_ERROR;
@ -497,12 +507,14 @@ ngx_rtmp_broadcast_publish(ngx_rtmp_session_t *s, double in_trans,
static ngx_int_t
ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, double in_trans,
ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_header_t sh;
static double trans;
static u_char pub_name[1024];
static u_char pub_type[1024];
static u_char play_name[1024];
static int bfalse;
static ngx_rtmp_amf0_elt_t out_inf[] = {
{ NGX_RTMP_AMF0_STRING, "code", NULL, 0 },
@ -510,10 +522,14 @@ ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, double in_trans,
{ NGX_RTMP_AMF0_STRING, "description", NULL, 0 },
};
static ngx_rtmp_amf0_elt_t out2_inf[] = {
{ NGX_RTMP_AMF0_STRING, "code", NULL, 0 },
};
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
{ NGX_RTMP_AMF0_NULL, NULL, NULL, 0 },
{ NGX_RTMP_AMF0_STRING, NULL, pub_name, sizeof(pub_name) },
{ NGX_RTMP_AMF0_STRING, NULL, pub_type, sizeof(pub_type) },
{ NGX_RTMP_AMF0_STRING, NULL, play_name, sizeof(play_name) },
};
static ngx_rtmp_amf0_elt_t out_elts[] = {
@ -523,6 +539,16 @@ ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, double in_trans,
{ NGX_RTMP_AMF0_OBJECT, NULL, out_inf, sizeof(out_inf) },
};
static ngx_rtmp_amf0_elt_t out2_elts[] = {
{ NGX_RTMP_AMF0_STRING, NULL, "onStatus", sizeof("onStatus") - 1 },
{ NGX_RTMP_AMF0_OBJECT, NULL, out2_inf, sizeof(out2_inf) },
};
static ngx_rtmp_amf0_elt_t out3_elts[] = {
{ NGX_RTMP_AMF0_STRING, NULL, "|RtmpSampleAccess", sizeof("|RtmpSampleAccess") - 1 },
{ NGX_RTMP_AMF0_BOOLEAN, NULL, &bfalse, sizeof(bfalse) },
};
if (ngx_rtmp_receive_amf0(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
@ -530,33 +556,133 @@ ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, double in_trans,
return NGX_ERROR;
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play() called; pubName='%s' pubType='%s'",
pub_name, pub_type);
play_name[0] = 0;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play() called; playame='%s'",
play_name);
if (ngx_rtmp_send_user_stream_begin(s, 1) != NGX_OK) {
return NGX_ERROR;
}
ngx_rtmp_broadcast_set_flags(s, NGX_RTMP_BROADCAST_SUBSCRIBER
| NGX_RTMP_BROADCAST_WANT_KEYFRAME);
trans = in_trans;
memset(&sh, 0, sizeof(sh));
sh.type = NGX_RTMP_MSG_AMF0_CMD;
sh.csid = 5; /*FIXME*/
sh.msid = h->msid;
ngx_str_set(&out_inf[0], "NetStream.Play.Reset");
ngx_str_set(&out_inf[1], "status");
ngx_str_set(&out_inf[2], "Playing and resetting.");
if (ngx_rtmp_send_amf0(s, &sh, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
{
return NGX_ERROR;
}
ngx_str_set(&out_inf[0], "NetStream.Play.Start");
ngx_str_set(&out_inf[1], "status");
ngx_str_set(&out_inf[2], "Started playing.");
if (ngx_rtmp_send_amf0(s, 3, 0, out_elts,
if (ngx_rtmp_send_amf0(s, &sh, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
{
return NGX_ERROR;
}
ngx_str_set(&out2_inf[0], "NetStream.Data.Start");
sh.type = NGX_RTMP_MSG_AMF0_META;
if (ngx_rtmp_send_amf0(s, &sh, out3_elts,
sizeof(out3_elts) / sizeof(out3_elts[0])) != NGX_OK)
{
return NGX_ERROR;
}
if (ngx_rtmp_send_amf0(s, &sh, out2_elts,
sizeof(out2_elts) / sizeof(out2_elts[0])) != NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}
static ngx_int_t ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s,
double in_trans, ngx_chain_t *in)
static ngx_int_t
ngx_rtmp_broadcast_set_data_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_connection_t *c;
ngx_rtmp_broadcast_ctx_t *ctx;
ngx_rtmp_amf0_ctx_t act;
ngx_rtmp_header_t sh;
static ngx_rtmp_amf0_elt_t out_elts[] = {
{ NGX_RTMP_AMF0_STRING, NULL,
"@setDataFrame", sizeof("@setDataFrame") - 1 },
};
c = s->connection;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_broadcast_module);
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, "data_frame arrived");
if (ctx->data_frame) {
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0,
"duplicate data_frame");
return NGX_OK;
}
/* create full metadata chain for output */
memset(&act, 0, sizeof(act));
act.arg = s;
act.alloc = ngx_rtmp_alloc_shared_buf;
act.log = c->log;
if (ngx_rtmp_amf0_write(&act, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
{
return NGX_ERROR;
}
if (act.first == NULL) {
return NGX_OK;
}
ctx->data_frame = act.first;
if (ngx_rtmp_append_shared_bufs(s, ctx->data_frame, in) == NULL) {
return NGX_ERROR;
}
memset(&sh, 0, sizeof(sh));
sh.csid = 5;
sh.msid = h->msid;
sh.type = h->type;
ngx_rtmp_addref_shared_bufs(ctx->data_frame);
ngx_rtmp_prepare_message(s, h, NULL, ctx->data_frame);
return NGX_OK;
}
static ngx_int_t
ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
static double trans;
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
};
static ngx_rtmp_amf0_elt_t out_inf[] = {
{ NGX_RTMP_AMF0_STRING, "code", NULL, 0 },
{ NGX_RTMP_AMF0_STRING, "level", NULL, 0 },
@ -570,10 +696,13 @@ static ngx_int_t ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s,
{ NGX_RTMP_AMF0_OBJECT, NULL, out_inf, sizeof(out_inf) },
};
if (ngx_rtmp_receive_amf0(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
trans = in_trans;
return ngx_rtmp_send_amf0(s, 3, 0, out_elts,
return ngx_rtmp_send_amf0(s, h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
}
@ -609,7 +738,7 @@ ngx_rtmp_broadcast_postconfiguration(ngx_conf_t *cf)
/* register AMF0 call handlers */
ncalls = sizeof(ngx_rtmp_broadcast_map)
/ sizeof(ngx_rtmp_broadcast_map[0]);
h = ngx_array_push_n(&cmcf->calls, ncalls);
h = ngx_array_push_n(&cmcf->amf0, ncalls);
if (h == NULL) {
return NGX_ERROR;
}

View file

@ -168,7 +168,7 @@ ngx_rtmp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_uint_value(conf->ack_window, prev->ack_window, 5000000);
if (prev->out_pool == NULL) {
prev->out_pool = ngx_create_pool(4096, cf->log);
prev->out_pool = ngx_create_pool(8192, cf->log);
if (prev->out_pool == NULL) {
return NGX_CONF_ERROR;
}

View file

@ -25,8 +25,8 @@ static ngx_int_t ngx_rtmp_receive_message(ngx_rtmp_session_t *s,
#ifdef NGX_DEBUG
static char*
ngx_rtmp_packet_type(uint8_t type) {
char*
ngx_rtmp_message_type(uint8_t type) {
static char* types[] = {
"?",
"chunk_size",
@ -57,6 +57,24 @@ ngx_rtmp_packet_type(uint8_t type) {
? types[type]
: "?";
}
char*
ngx_rtmp_user_message_type(uint16_t evt) {
static char* evts[] = {
"stream_begin",
"stream_eof",
"stream dry",
"set_buflen",
"recorded",
"ping_request",
"ping_response",
};
return evt < sizeof(evts) / sizeof(evts[0])
? evts[evt]
: "?";
}
#endif
void
@ -216,14 +234,12 @@ ngx_rtmp_init_session(ngx_connection_t *c)
ngx_rtmp_close_connection(c);
return;
}
size = NGX_RTMP_HANDSHAKE_SIZE + 1;
s->in_chunk_size = NGX_RTMP_DEFAULT_CHUNK_SIZE;
s->in_pool = ngx_create_pool(2 * (NGX_RTMP_HANDSHAKE_SIZE + 1)
+ sizeof(ngx_pool_t), c->log);
s->in_pool = ngx_create_pool(2 * size + sizeof(ngx_pool_t), c->log);
/* start handshake */
size = NGX_RTMP_HANDSHAKE_SIZE + 1;
b = &s->hs_in_buf;
b->start = b->pos = b->last = ngx_pcalloc(s->in_pool, size);
b->end = b->start + size;
@ -350,7 +366,7 @@ ngx_rtmp_handshake_recv(ngx_event_t *rev)
}
/* reply timestamp is the same as out epoch */
ngx_memcpy(s->hs_in_buf.pos + 4, b->pos + 1, 4);
/*ngx_memcpy(s->hs_in_buf.pos + 4, b->pos + 1, 4);*/
ngx_rtmp_handshake_send(c->write);
@ -439,6 +455,8 @@ restart:
ngx_rtmp_handshake_recv(c->read);
}
ngx_chain_t * tmp;
void
ngx_rtmp_recv(ngx_event_t *rev)
@ -483,6 +501,10 @@ ngx_rtmp_recv(ngx_event_t *rev)
return;
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0,
"allocating input buffer %p : %p",
st->in, st->in->buf);
st->in->next = NULL;
b = st->in->buf;
size = s->in_chunk_size + NGX_RTMP_MAX_CHUNK_HEADER;
@ -577,7 +599,7 @@ ngx_rtmp_recv(ngx_event_t *rev)
if (csid >= cscf->max_streams) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ERROR,
"RTMP chunk stream too big: %D >= %D",
"RTMP in chunk stream too big: %D >= %D",
csid, cscf->max_streams);
ngx_rtmp_close_connection(c);
return;
@ -648,12 +670,13 @@ ngx_rtmp_recv(ngx_event_t *rev)
if (timestamp == 0x00ffffff) {
if (b->last - p < 4)
continue;
pp = (u_char*)&h->timestamp;
pp = (u_char*)&timestamp;
pp[3] = *p++;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
} else if (fmt) {
}
if (fmt) {
h->timestamp += timestamp;
} else {
h->timestamp = timestamp;
@ -662,10 +685,15 @@ ngx_rtmp_recv(ngx_event_t *rev)
ngx_log_debug6(NGX_LOG_DEBUG_RTMP, c->log, 0,
"RTMP mheader %s (%d) "
"timestamp=%D mlen=%D len=%D msid=%D",
ngx_rtmp_packet_type(h->type), (int)h->type,
"timestamp=%uD mlen=%D len=%D msid=%D",
ngx_rtmp_message_type(h->type), (int)h->type,
h->timestamp, h->mlen, st->len, h->msid);
if (h->mlen==51441 && st->len==20864) {
/*asm("int $0x03");*/
tmp = in;
}
/* header done */
b->pos = p;
}
@ -689,7 +717,8 @@ ngx_rtmp_recv(ngx_event_t *rev)
/* handle! */
head = st->in->next;
st->in->next = NULL;
old_pos = b->pos + fsize;
b->last = b->pos + fsize;
old_pos = b->last;
old_size = size - fsize;
st->len = 0;
@ -713,7 +742,6 @@ ngx_rtmp_recv(ngx_event_t *rev)
#define ngx_rtmp_buf_addref(b) \
(++*(int*)&((b)->tag))
#define ngx_rtmp_buf_release(b) \
(--*(int*)&((b)->tag))
@ -725,6 +753,7 @@ ngx_rtmp_send(ngx_event_t *wev)
ngx_rtmp_session_t *s;
ngx_rtmp_core_srv_conf_t *cscf;
ngx_chain_t *out, *l;
u_char *p;
c = wev->data;
s = c->data;
@ -747,6 +776,8 @@ ngx_rtmp_send(ngx_event_t *wev)
}
while (s->out) {
p = s->out->buf->pos;
out = c->send_chain(c, s->out, 0);
if (out == NGX_CHAIN_ERROR) {
@ -754,9 +785,7 @@ ngx_rtmp_send(ngx_event_t *wev)
return;
}
if (out == s->out
&& out->buf->pos == out->buf->last)
{
if (out == s->out && out->buf->pos == p) {
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
ngx_add_timer(c->write, cscf->timeout);
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
@ -769,7 +798,7 @@ ngx_rtmp_send(ngx_event_t *wev)
l = s->out;
if (l->buf->pos < l->buf->last) {
l->buf->pos = l->buf->last;
/*l->buf->pos = l->buf->last;*/
break;
}
@ -784,7 +813,7 @@ ngx_rtmp_send(ngx_event_t *wev)
}
/* return buffer to core */
if (ngx_rtmp_release_shared_buf(s, l)) {
if (ngx_rtmp_free_shared_buf(s, l)) {
ngx_rtmp_close_connection(c);
return;
}
@ -815,14 +844,7 @@ ngx_rtmp_alloc_shared_buf(ngx_rtmp_session_t *s)
out = cscf->out_free;
cscf->out_free = out->next;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0,
"reuse shared buf");
} else {
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0,
"alloc shared buf");
out = ngx_alloc_chain_link(cscf->out_pool);
if (out == NULL) {
return NULL;
@ -850,8 +872,74 @@ ngx_rtmp_alloc_shared_buf(ngx_rtmp_session_t *s)
}
ngx_chain_t *
ngx_rtmp_append_shared_bufs(ngx_rtmp_session_t *s, ngx_chain_t *out,
ngx_chain_t *in)
{
ngx_connection_t *c;
ngx_chain_t *l, **ll;
u_char *p;
size_t size;
c = s->connection;
ll = &out;
p = in->buf->pos;
l = out;
if (l) {
for(; l->next; l = l->next);
ll = &l->next;
}
for ( ;; ) {
if (l == NULL || l->buf->last == l->buf->end) {
l = ngx_rtmp_alloc_shared_buf(s);
if (l == NULL || l->buf == NULL) {
return NULL;
}
*ll = l;
ll = &l->next;
}
while (l->buf->end - l->buf->last >= in->buf->last - p) {
l->buf->last = ngx_cpymem(l->buf->last, p,
in->buf->last - p);
in = in->next;
if (in == NULL) {
goto done;
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0,
"copy link %p : %p", in, in->buf);
p = in->buf->pos;
}
size = l->buf->end - l->buf->last;
l->buf->last = ngx_cpymem(l->buf->last, p, size);
p += size;
}
done:
*ll = NULL;
return out;
}
ngx_int_t
ngx_rtmp_release_shared_buf(ngx_rtmp_session_t *s,
ngx_rtmp_addref_shared_bufs(ngx_chain_t *in)
{
for(; in; in = in->next) {
ngx_rtmp_buf_addref(in->buf);
}
return NGX_OK;
}
ngx_int_t
ngx_rtmp_free_shared_buf(ngx_rtmp_session_t *s,
ngx_chain_t *out)
{
ngx_rtmp_core_srv_conf_t *cscf;
@ -875,14 +963,28 @@ ngx_rtmp_release_shared_buf(ngx_rtmp_session_t *s,
void
ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *out, uint8_t fmt)
ngx_rtmp_header_t *lh, ngx_chain_t *out)
{
ngx_chain_t *l;
u_char *p, *pp;
ngx_int_t hsize, thsize, nbufs;
uint32_t mlen, timestamp, ext_timestamp;
static uint8_t hdrsize[] = { 12, 8, 4, 1 };
u_char th[3];
ngx_chain_t *l;
u_char *p, *pp;
ngx_int_t hsize, thsize, nbufs;
uint32_t mlen, timestamp, ext_timestamp;
static uint8_t hdrsize[] = { 12, 8, 4, 1 };
u_char th[3];
ngx_rtmp_core_srv_conf_t *cscf;
uint8_t fmt;
ngx_connection_t *c;
c = s->connection;
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
if (h->csid >= cscf->max_streams) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ERROR,
"RTMP out chunk stream too big: %D >= %D",
h->csid, cscf->max_streams);
ngx_rtmp_close_connection(c);
return;
}
/* detect packet size */
mlen = 0;
@ -892,22 +994,40 @@ ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
++nbufs;
}
ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"RTMP prep %s (%d) fmt=%d csid=%D timestamp=%D "
"mlen=%D msid=%D nbufs=%d",
ngx_rtmp_packet_type(h->type), (int)h->type, (int)fmt,
h->csid, h->timestamp, mlen, h->msid, nbufs);
/* determine initial header size */
hsize = hdrsize[fmt];
if (h->timestamp >= 0x00ffffff) {
timestamp = 0x00ffffff;
ext_timestamp = h->timestamp;
hsize += 4;
fmt = 0;
if (lh && lh->csid && h->msid == lh->msid) {
++fmt;
if (h->type == lh->type
&& mlen == lh->mlen)
{
++fmt;
if (h->timestamp == lh->timestamp) {
++fmt;
}
}
timestamp = h->timestamp - lh->timestamp;
} else {
timestamp = h->timestamp;
ext_timestamp = 0;
}
if (lh) {
*lh = *h;
lh->mlen = mlen;
}
hsize = hdrsize[fmt];
ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"RTMP prep %s (%d) fmt=%d csid=%uD timestamp=%uD "
"mlen=%uD msid=%uD nbufs=%d",
ngx_rtmp_message_type(h->type), (int)h->type, (int)fmt,
h->csid, h->timestamp, h->mlen, h->msid, nbufs);
ext_timestamp = 0;
if (timestamp >= 0x00ffffff) {
ext_timestamp = timestamp;
timestamp = 0x00ffffff;
hsize += 4;
}
if (h->csid >= 64) {
@ -1041,7 +1161,7 @@ ngx_rtmp_receive_message(ngx_rtmp_session_t *s,
ngx_log_debug7(NGX_LOG_DEBUG_RTMP, c->log, 0,
"RTMP recv %s (%d) csid=%D timestamp=%D "
"mlen=%D msid=%D nbufs=%d",
ngx_rtmp_packet_type(h->type), (int)h->type,
ngx_rtmp_message_type(h->type), (int)h->type,
h->csid, h->timestamp, h->mlen, h->msid, nbufs);
}
#endif
@ -1107,6 +1227,11 @@ ngx_rtmp_close_connection(ngx_connection_t *c)
}
}
if (s->out) {
ngx_rtmp_free_shared_buf(s, s->out);
s->out = NULL;
}
c->destroyed = 1;
pool = c->pool;
ngx_close_connection(c);

View file

@ -95,6 +95,10 @@ ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s,
p[0] = b->pos[1];
p[1] = b->pos[0];
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0,
"RTMP recv user evt %s (%d)",
ngx_rtmp_user_message_type(evt), (int)evt);
p = (u_char*)&val;
p[0] = b->pos[5];
p[1] = b->pos[4];
@ -159,7 +163,7 @@ ngx_rtmp_amf0_message_handler(ngx_rtmp_session_t *s,
ngx_rtmp_amf0_ctx_t act;
ngx_connection_t *c;
ngx_rtmp_core_main_conf_t *cmcf;
ngx_rtmp_call_handler_pt ch;
ngx_rtmp_event_handler_pt ch;
size_t len;
static double trans;
@ -167,7 +171,6 @@ ngx_rtmp_amf0_message_handler(ngx_rtmp_session_t *s,
static ngx_rtmp_amf0_elt_t elts[] = {
{ NGX_RTMP_AMF0_STRING, 0, func, sizeof(func) },
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
};
c = s->connection;
@ -192,14 +195,14 @@ ngx_rtmp_amf0_message_handler(ngx_rtmp_session_t *s,
* only the first handler is called so far
* because ngx_hash_find only returns one item;
* no good to patch NGINX core ;) */
ch = ngx_hash_find(&cmcf->calls_hash,
ch = ngx_hash_find(&cmcf->amf0_hash,
ngx_hash_strlow(func, func, len), func, len);
if (ch) {
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0,
"AMF0 func '%s' trans=%f passed to handler", func, trans);
return ch(s, trans, in);
return ch(s, h, in);
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0,

View file

@ -36,7 +36,7 @@
*(__b->last++) = ((u_char*)&v)[0];
#define NGX_RTMP_USER_END(s) \
ngx_rtmp_prepare_message(s, &__h, __l, 0); \
ngx_rtmp_prepare_message(s, &__h, NULL, __l); \
return ngx_rtmp_send_message(s, __l); \
@ -180,10 +180,9 @@ ngx_rtmp_send_user_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp)
/* AMF0 sender */
ngx_int_t
ngx_rtmp_send_amf0(ngx_rtmp_session_t *s, uint32_t csid, uint32_t msid,
ngx_rtmp_send_amf0(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_amf0_elt_t *elts, size_t nelts)
{
ngx_rtmp_header_t h;
ngx_rtmp_amf0_ctx_t act;
memset(&act, 0, sizeof(act));
@ -191,17 +190,12 @@ ngx_rtmp_send_amf0(ngx_rtmp_session_t *s, uint32_t csid, uint32_t msid,
act.alloc = ngx_rtmp_alloc_shared_buf;
act.log = s->connection->log;
memset(&h, 0, sizeof(h));
h.type = NGX_RTMP_MSG_AMF0_CMD;
h.csid = csid;
h.msid = msid;
if (ngx_rtmp_amf0_write(&act, elts, nelts) != NGX_OK) {
return NGX_ERROR;
}
if (act.first) {
ngx_rtmp_prepare_message(s, &h, act.first, 0);
ngx_rtmp_prepare_message(s, h, NULL, act.first);
return ngx_rtmp_send_message(s, act.first);
}