<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
<span class="Apple-tab-span" style="white-space:pre">        </span>I'm new to mailing lists so please forgive me if I break any protocols...<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>I've been trying to encode video using libtheora-1.1.1 and libogg-1.1.4 on a Win32 system. &nbsp;While I did have to change the code in order to get them to compile, I'm assuming they're correct. &nbsp;With that assumption, the video I make with them plays way too fast. &nbsp;Either the framerate is interpreted by players to be way too high or not all the frames are getting encoded in the stream. &nbsp;Media reporting software (like MediaInfo) report the correct framerate from the ogg file. &nbsp;I will post the test code that I'm using so people can take a cursory look and see if there are any obvious mistakes that I'm making. &nbsp;If anyone actually wants to compile the code, I can post a version of it that doesn't use an external image library, in this case CxImage.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Any help is greatly appreciated. &nbsp;Thank you!</div><div><br></div><div><br></div><div><br></div><div><br></div><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>// Rounds to the next multiple of 16</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>// This is a cheap transform but it will do for a simple test</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>// This is done so often that we might as well factor it out</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>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>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>}</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(image.GetWidth());</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.frame_height = RoundTo16(image.GetHeight());</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_width = image.GetWidth();</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theora_input.pic_height = image.GetHeight();</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_444;</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 = 30;</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 temp = 5;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>//th_encode_ctl(theora_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, &amp;temp, sizeof(temp));</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_GET_SPLEVEL_MAX, &amp;temp, sizeof(temp));</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_SET_SPLEVEL &nbsp; &nbsp;, &amp;temp, sizeof(temp));</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; &nbsp;// Does it really matter what this is?</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 = {0};</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>ogg_stream_packetin(&amp;ogg_state, &amp;packet); &nbsp; &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; &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>for(int i = 0; i &lt; 3; i++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>buffer[i].width = theora_input.frame_width;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>buffer[i].height = theora_input.frame_height;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>buffer[i].stride = theora_input.frame_width;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>buffer[i].data = new unsigned char[theora_input.frame_width * theora_input.frame_height];</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>for(DWORD y = 0; y &lt; image.GetHeight(); y++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>for(DWORD x = 0; x &lt; image.GetWidth(); x++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>buffer[i].data[y * buffer[i].stride + x] = TransformPixel(tables[i], image.GetPixelColor(x, image.GetHeight() - 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>printf("Encoding video...\n");</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>int num_frames = 30 * 10; &nbsp; &nbsp;// This should be 10 seconds of video but it ends up being about 3...</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>for(int i = 0; i &lt; num_frames; i++) {</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 []&nbsp;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 /><hr /> <a href='' target='_new'></a></body>
</html>