<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. While I did have to change the code in order to get them to compile, I'm assuming they're correct. With that assumption, the video I make with them plays way too fast. Either the framerate is interpreted by players to be way too high or not all the frames are getting encoded in the stream. Media reporting software (like MediaInfo) report the correct framerate from the ogg file. 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. 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. Thank you!</div><div><br></div><div><br></div><div><br></div><div><br></div><div><div>#include <stdio.h></div><div>//#include <conio.h></div><div>#include <assert.h></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<unsigned char>(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( state, &page);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>else rc = ogg_stream_pageout(state, &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 < 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(&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(&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, &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, &temp, sizeof(temp));</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>th_encode_ctl(theora_state, TH_ENCCTL_SET_SPLEVEL , &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(&ogg_state, 3001); // 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, &comment, &packet);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ogg_stream_packetin(&ogg_state, &packet); // Can this really fail?</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>WriteOggPage(output_file, &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, &comment, &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(&ogg_state, &packet); // 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, &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 < 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 < image.GetHeight(); y++) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>for(DWORD x = 0; x < 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; // 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 < 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, &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(&ogg_state, &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, &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, &ogg_state, true);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>for(int i = 0; i < 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(&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>