<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
<br>&gt; Date: Wed, 17 Feb 2010 19:15:55 -0500<br>&gt; From: tterribe@email.unc.edu<br>&gt; <br>&gt; Id Kong wrote:<br>&gt; &gt; Is the encoding control command TH_ENCCTL_SET_DUP_COUNT compatible with<br>&gt; &gt; the TH_ENCCTL_SET_VP3_COMPATIBLE setting?<br>&gt; <br>&gt; It should be. Can you upload some input that exhibits the problem and<br>&gt; (hopefully) the source code you're using to set the dup counts, or at<br>&gt; least the actual counts used with that input?<br><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>I've created a small sample program that exhibits the behavior. &nbsp;I've created video with this program with and without the&nbsp;TH_ENCCTL_SET_DUP_COUNT used for each frame and I've played back the results with ffdshow tryout revision 1980 (Jun 2, 2008. &nbsp;I found the about box!) and with VLC player 1.0.2 (Goldeneye), so I have two different players and two different ogg/theora streams...</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ffdshow has trouble playing this particular&nbsp;TH_ENCCTL_SET_VP3_COMPATIBLE file, without any&nbsp;TH_ENCCTL_SET_DUP_COUNT,&nbsp;for some odd reason since it plays other ogg/theora files with these properties just fine. &nbsp;It plays the first little bit but quickly thinks it's reached the end of the file when it's really nowhere close...</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>VLC has no trouble playing this particular&nbsp;TH_ENCCTL_SET_VP3_COMPATIBLE file lacking any&nbsp;TH_ENCCTL_SET_DUP_COUNT.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ffdshow exhibits the strange green behavior I mentioned in my original post with both the&nbsp;TH_ENCCTL_SET_VP3_COMPATIBLE setting and with&nbsp;TH_ENCCTL_SET_DUP_COUNT applied to every frame, as you can see in the code. &nbsp;All the timing works but the green is definitely a bug!</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>VLC can play the file with no green but it's obviously wrong about the timing. &nbsp;It starts off with just black, then it sometimes plays smoothly, as if there are no duplicate frames, but occasionally pauses, way too long to simply be an additional frame, as was coded in the program. &nbsp;It's as if it ignores the use of&nbsp;TH_ENCCTL_SET_DUP_COUNT until they pile up and it's forced to use them up all at once.</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Here's my sample program. &nbsp;Like my previous sample program, it uses CxImage, so if you want to actually compile the program, I can create an include file with this image statically created in C++ syntax...</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Thank you for your help!</div><div><br></div><div><br></div><div><br></div><div><div><br></div><div>#include &lt;stdio.h&gt;</div><div>//#include &lt;conio.h&gt;</div><div>#include &lt;assert.h&gt;</div><div><br></div><div>#include "CxImage\ximage.h"</div><div>#include "theora\theoraenc.h"</div><div>#include "theora\codec.h"</div><div><br></div><div><br></div><div>int const frame_rate = 30;</div><div>//int const num_frames = frame_rate * 10;</div><div>int const width = 320;</div><div>int const height = 240;</div><div><br></div><div><br></div><div>int RoundTo16(int in) {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>return (in + 15) / 16 * 16;</div><div>}</div><div><br></div><div>unsigned char TransformPixel(int *tables, RGBQUAD colour) {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>return static_cast&lt;unsigned char&gt;(tables[0] + (tables[1] * colour.rgbRed + tables[2] * colour.rgbGreen + tables[3] * colour.rgbBlue) / 256);</div><div>}</div><div><br></div><div>void WriteOggPage(FILE *file, ogg_stream_state *state, bool flush = false) {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>while(true) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ogg_page page;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>int rc;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>if( flush ) rc = ogg_stream_flush( &nbsp;state, &amp;page);</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>else &nbsp; &nbsp; &nbsp; &nbsp;rc = ogg_stream_pageout(state, &amp;page);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>if( rc == 0 ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>break;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>fwrite(page.header, 1, page.header_len, file);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>fwrite(page.body, 1, page.body_len, file);</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div>}</div><div><br></div><div><br></div><div>int main(int argc, char *argv[]) {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if( argc &lt; 3 ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>printf("Too few parameters...\n");</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>char *input_filename = argv[1];</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>char *output_filename = argv[2];</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>CxImage image;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>image.Load(input_filename);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>if( image.IsValid() ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>printf("Loaded image!\n");</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_info theora_input;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_info_init(&amp;theora_input);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.frame_width = RoundTo16(width);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.frame_height = RoundTo16(height);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_width = width;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_height = height;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_x = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_y = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.colorspace = TH_CS_UNSPECIFIED;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pixel_fmt = TH_PF_420;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.quality = 42;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.target_bitrate = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.fps_numerator = frame_rate;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.fps_denominator = 1;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.aspect_numerator = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.aspect_denominator = 0;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_enc_ctx *theora_state = th_encode_alloc(&amp;theora_input);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>int th_ctl = 5;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_GET_SPLEVEL_MAX, &amp;th_ctl, sizeof(th_ctl));</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_SET_SPLEVEL &nbsp; &nbsp;, &amp;th_ctl, sizeof(th_ctl));</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_ctl = 1;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>// Strangely enough, pixel format TH_PF_420 doesn't seem to work without the TH_ENCCTL_SET_VP3_COMPATIBLE setting...</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_SET_VP3_COMPATIBLE, &amp;th_ctl, sizeof(th_ctl));</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_stream_state ogg_state;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_stream_init(&amp;ogg_state, 3001); &nbsp;// Yeah, I know...</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>FILE* output_file = fopen(output_filename, "wb");</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_packet packet;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool go = true;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_comment comment;</div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_comment_init(&amp;comment);&nbsp;<div><span class="Apple-tab-span" style="white-space:pre">                        </span>int rc = th_encode_flushheader(theora_state, &amp;comment, &amp;packet);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_stream_packetin(&amp;ogg_state, &amp;packet); &nbsp;// Can this really fail?</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>WriteOggPage(output_file, &amp;ogg_state, true);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>while(true) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>int rc = th_encode_flushheader(theora_state, &amp;comment, &amp;packet);</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>//printf("%i\n", packet.packetno);</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>if( rc == 0) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>printf("Done headers!\n");</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>break;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>printf("Another packet...\n");</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ogg_stream_packetin(&amp;ogg_state, &amp;packet); &nbsp;// Can this really fail?</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>WriteOggPage(output_file, &amp;ogg_state, true);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>if( go ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>printf("Preparing frame...\n");</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>th_ycbcr_buffer buffer;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>int tables[][4] = {{16, 66, 129, 25}, {128, -38, -74, 112}, {128, 112, -94, -18}};</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>printf("Encoding video...\n");</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>int num_frames = image.GetWidth() - width;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>for(int i = 0; i &lt; num_frames; i++) {</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>// Fill the buffer with a pan of a small subset of the image so</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>// that we are encoding animation and not just a static image...</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>for(int j = 0; j &lt; 3; j++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>th_img_plane *plane = buffer + j;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>if( j == 0 ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>plane-&gt;width = theora_input.pic_width;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>plane-&gt;height = theora_input.pic_height;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>plane-&gt;width = theora_input.pic_width / 2;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>plane-&gt;height = theora_input.pic_height / 2;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>plane-&gt;stride = plane-&gt;width;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>plane-&gt;data = new unsigned char[plane-&gt;width * plane-&gt;height];</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>for(DWORD y = 0; y &lt; height; y++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>for(DWORD x = 0; x &lt; width; x++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>// the sum x + i creates our animation...</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>if( j == 0 )</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                        </span>plane-&gt;data[y * plane-&gt;stride &nbsp; &nbsp; + x &nbsp; &nbsp;] = TransformPixel(tables[j], image.GetPixelColor(x + i, height - y, false));</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>else if( x % 2 == 0 &amp;&amp; y % 2 == 0 )</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                        </span>plane-&gt;data[y * plane-&gt;stride / 2 + x / 2] = TransformPixel(tables[j], image.GetPixelColor(x + i, height - y, false));</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>int dupes = 1;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>th_encode_ctl(theora_state, TH_ENCCTL_SET_DUP_COUNT, &amp;dupes, sizeof(dupes));</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>int rc = th_encode_ycbcr_in(theora_state, buffer);</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>if( rc == 0 ) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>while(true) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>int rc = th_encode_packetout(theora_state, (i == num_frames - 1) ? 1 : 0, &amp;packet);</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>if( rc == 0 ) break;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>ogg_stream_packetin(&amp;ogg_state, &amp;packet);</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>WriteOggPage(output_file, &amp;ogg_state);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>printf("Encoding error was encountered!\n");</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>break;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>WriteOggPage(output_file, &amp;ogg_state, true);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>for(int i = 0; i &lt; 3; i++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>delete [] buffer[i].data;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>fclose(output_file);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>printf("Done encoding!\n");</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_stream_clear(&amp;ogg_state);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_free(theora_state);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>} else {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>printf("Bad image input...\n");</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>//_getch();</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>return 0;</div><div>}</div><div><br></div></div>                                               <br /><hr />All your Hotmail contacts on your phone. <a href='http://go.microsoft.com/?linkid=9708118' target='_new'>Try it now.</a></body>
</html>