2009-11-15 7 views

उत्तर

3

यहाँ libtheora API और example code है।

यहां एक micro howto है जो दिखाता है कि थियोरा बाइनरी का उपयोग कैसे करें। चूंकि एन्कोडर वीडियो के लिए कच्चे, असम्पीडित 'yuv4mpeg' डेटा को पढ़ता है, तो आप वीडियो एप को एन्कोडर पर पाइप करके भी अपने ऐप से इसका उपयोग कर सकते हैं।

9

संपूर्ण समाधान यहां कोड नमूना के रूप में पोस्ट करने के लिए थोड़ा लंबा है, लेकिन यदि आप Xiph.org से libtheora डाउनलोड करते हैं, तो एक उदाहरण png2theora है। मेरे द्वारा उल्लेख किए जाने वाले सभी पुस्तकालय कार्यों को थियोरा और ओग के लिए Xiph.org पर प्रलेखन में पाया जा सकता है।

  1. th_info_init() को th_info संरचना आरंभ करने के लिए कॉल करें, फिर उसमें उचित सदस्यों को निर्दिष्ट करके आउटपुट पैरामीटर सेट करें।
  2. th_encode_alloc के लिए एक कॉल में है कि संरचना का उपयोग करें() एक एनकोडर संदर्भ
  3. प्राप्त करने के लिए एक ogg धारा Initialise, ogg_stream_init()
  4. साथ निम्नलिखित के माध्यम से th_comment_init

दोहराएं का उपयोग कर एक खाली th_comment संरचना Initialise :

  1. एन्कोडर संदर्भ, रिक्त टिप्पणी संरचना और एक ogg_packet के साथ th_encode_flushheader पर कॉल करें।
  2. page.header लेखन ogg_stream_packetin()

th_encode_flushheader तक रिटर्न 0 (या एक त्रुटि कोड)

साथ ogg धारा के परिणामस्वरूप पैकेट भेजें अब, बार-बार फोन ogg_stream_pageout(), हर बार और उसके बाद पृष्ठ। किसी आउटपुट फ़ाइल में, जब तक यह 0 न हो जाए। अब ogg_stream_flush को कॉल करें और परिणामी पृष्ठ को फ़ाइल में लिखें।

अब आप एन्कोडर में फ्रेम लिख सकते हैं। यहाँ है कैसे मैंने किया:

int theora_write_frame(int outputFd, unsigned long w, unsigned long h, unsigned char *yuv_y, unsigned char *yuv_u, unsigned char *yuv_v, int last) 
{ 
    th_ycbcr_buffer ycbcr; 
    ogg_packet op; 
    ogg_page og; 

    unsigned long yuv_w; 
    unsigned long yuv_h; 

    /* Must hold: yuv_w >= w */ 
    yuv_w = (w + 15) & ~15; 
    /* Must hold: yuv_h >= h */ 
    yuv_h = (h + 15) & ~15; 

    //Fill out the ycbcr buffer 
    ycbcr[0].width = yuv_w; 
    ycbcr[0].height = yuv_h; 
    ycbcr[0].stride = yuv_w; 
    ycbcr[1].width = yuv_w; 
    ycbcr[1].stride = ycbcr[1].width; 
    ycbcr[1].height = yuv_h; 
    ycbcr[2].width = ycbcr[1].width; 
    ycbcr[2].stride = ycbcr[1].stride; 
    ycbcr[2].height = ycbcr[1].height; 

    if(encoderInfo->pixel_fmt == TH_PF_420) 
    { 
    //Chroma is decimated by 2 in both directions 
    ycbcr[1].width = yuv_w >> 1; 
    ycbcr[2].width = yuv_w >> 1; 
    ycbcr[1].height = yuv_h >> 1; 
    ycbcr[2].height = yuv_h >> 1; 
    }else if(encoderInfo->pixel_fmt == TH_PF_422) 
    { 
    ycbcr[1].width = yuv_w >> 1; 
    ycbcr[2].width = yuv_w >> 1; 
    }else if(encoderInfo->pixel_fmt != TH_PF_422) 
    { 
    //Then we have an unknown pixel format 
    //We don't know how long the arrays are! 
    fprintf(stderr, "[theora_write_frame] Unknown pixel format in writeFrame!\n"); 
    return -1; 
    } 

    ycbcr[0].data = yuv_y; 
    ycbcr[1].data = yuv_u; 
    ycbcr[2].data = yuv_v; 

    /* Theora is a one-frame-in,one-frame-out system; submit a frame 
    for compression and pull out the packet */ 
    if(th_encode_ycbcr_in(encoderContext, ycbcr)) { 
    fprintf(stderr, "[theora_write_frame] Error: could not encode frame\n"); 
    return -1; 
    } 

    if(!th_encode_packetout(encoderContext, last, &op)) { 
    fprintf(stderr, "[theora_write_frame] Error: could not read packets\n"); 
    return -1; 
    } 

    ogg_stream_packetin(&theoraStreamState, &op); 
    ssize_t bytesWritten = 0; 
    int pagesOut = 0; 
    while(ogg_stream_pageout(&theoraStreamState, &og)) { 
    pagesOut ++; 
    bytesWritten = write(outputFd, og.header, og.header_len); 
    if(bytesWritten != og.header_len) 
    { 
     fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n"); 
     return -1; 
    } 
    bytesWritten = write(outputFd, og.body, og.body_len); 
    if(bytesWritten != og.body_len) 
    { 
     bytesWritten = fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n"); 
     return -1; 
    } 
    } 
    return pagesOut; 
} 

कहाँ encoderInfo th_info एनकोडर (मेरे लिए डेटा अनुभाग में स्थिर) आरंभ करने के लिए इस्तेमाल संरचना है।

अपने अंतिम फ्रेम पर, th_encode_packetout() पर अंतिम फ्रेम सेट करने से यह सुनिश्चित हो जाएगा कि स्ट्रीम ठीक से समाप्त हो जाए।

एक बार ऐसा करने के बाद, बस साफ करना सुनिश्चित करें (मुख्य रूप से fds बंद करना)। th_info_clear() th_info संरचना को साफ़ कर देगा, और th_encode_free() आपके एन्कोडर संदर्भ को मुक्त कर देगा।

जाहिर है, आपको अपने बिटमैप को YUV विमानों में कनवर्ट करने से पहले आपको theora_write_frame() में स्थानांतरित करने की आवश्यकता होगी।

आशा है कि यह कुछ मदद की है। सौभाग्य!

संबंधित मुद्दे