2012-03-11 25 views
9

मैं libavcodec के माध्यम से वीडियो को डिकोड, निम्नलिखित कोड का उपयोग कर:libavcodec में डीकोड पिक्सेल प्रारूप कैसे सेट करें?

//Open input file 
if(avformat_open_input(&ctx, filename, NULL, NULL)!=0) 
    return FALSE; // Couldn't open file 
if(avformat_find_stream_info(ctx, NULL)<0) 
    return FALSE; // Couldn't find stream information 
videoStream = -1; 
//find video stream 
for(i=0; i<ctx->nb_streams; i++) 
{  
    if((ctx->streams[i])->codec->codec_type==AVMEDIA_TYPE_VIDEO) 
    { 
     videoStream=i; 
     break; 
    } 
} 
if (videoStream == -1) 
    return FALSE; // Didn't find a video stream 
video_codec_ctx=ctx->streams[videoStream]->codec; 
//find decoder 
video_codec=avcodec_find_decoder(video_codec_ctx->codec_id); 
if(video_codec==NULL) 
    return FALSE; // Codec not found 
if(avcodec_open(video_codec_ctx, video_codec)<0) 
    return -1; // Could not open codec 
video_frame=avcodec_alloc_frame(); 
scaled_frame=avcodec_alloc_frame(); 
static struct SwsContext *img_convert_ctx; 
if(img_convert_ctx == NULL) 
{ 
     int w = video_codec_ctx->width; 
     int h = video_codec_ctx->height; 
     img_convert_ctx = sws_getContext(w, h, 
         video_codec_ctx->pix_fmt, 
         w, h, dst_pix_fmt, SWS_BICUBIC, 
         NULL, NULL, NULL); 
     if(img_convert_ctx == NULL) { 
     fprintf(stderr, "Cannot initialize the conversion context!\n"); 
     return FALSE; 
     } 
} 
while(b_play) 
{ 
    if (av_read_frame(ctx, &packet) < 0) 
    { 
     break; 
    } 
    if(packet.stream_index==videoStream) { 
    // Decode video frame 
     avcodec_decode_video2(video_codec_ctx, video_frame, &frameFinished, 
         &packet); 
     // Did we get a video frame? 
     if(frameFinished) 
     { 
      if (video_codec_ctx->pix_fmt != dst_pix_fmt) 
      {      
       if (video_codec_ctx->pix_fmt != dst_pix_fmt)    
        sws_scale(img_convert_ctx, video_frame->data, 
           video_frame->linesize, 0, 
           video_codec_ctx->height, 
           scaled_frame->data, scaled_frame->linesize);    
      }   
     } 
} 
av_free_packet(&packet); 
} 

कोड ठीक से कार्य लेकिन यह आवश्यक प्रारूप करने के लिए प्रत्येक फ्रेम कन्वर्ट करने के लिए आवश्यक है। क्या sws_scale के बिना सही प्रारूप प्राप्त करने के लिए डीकोडिंग के लिए पिक्सेल प्रारूप सेट करना संभव है?

आपके उत्तरों के लिए बहुत धन्यवाद।

उत्तर

14

ffmpeg के AVCodec उदाहरणों (स्थिर विकोडक "फैक्टरी" वस्तुओं) प्रत्येक पिक्सेल प्रारूपों है कि वे समर्थन करते हैं, मूल्य -1 द्वारा समाप्त की एक सरणी परिभाषित करते हैं।

AVCodecContext (डिकोडर इंस्टेंस) ऑब्जेक्ट्स में कॉलबैक फ़ंक्शन पॉइंटर होता है जिसेकहा जाता है: यह उस संरचना में फ़ंक्शन पॉइंटर है।

यह कॉलबैक फ़ंक्शन कोडेक प्रारंभिकरण में किसी बिंदु पर AVCodec फैक्ट्री ऑब्जेक्ट की समर्थित प्रारूपों की सरणी के साथ बुलाया जाता है, और कॉलबैक को उस सरणी के प्रारूपों में से एक चुनना होता है (जैसे "कार्ड चुनें , कोई कार्ड ") और उस मूल्य को वापस करें। इस get_format कॉलबैक का डिफ़ॉल्ट कार्यान्वयन avcodec_default_get_format नामक एक फ़ंक्शन है। (यह avcodec_get_context_defaults2 स्थापित है)। यह डिफ़ॉल्ट फ़ंक्शन "प्रारूप चुनें" तर्क को सरलता से लागू करता है: यह सरणी का पहला तत्व चुनता है जो हार्डवेयर-एक्सेल-केवल पिक्सेल प्रारूप नहीं है।

यदि आप कोडेक को एक अलग पिक्सेल प्रारूप के साथ काम करना चाहते हैं, तो आप अपने ऑब्जेक्ट में get_format कॉलबैक इंस्टॉल कर सकते हैं। हालांकि, कॉलबैक को सरणी में मानों में से एक को वापस करना होगा (जैसे मेनू से चुनना)। यह एक मनमाना मूल्य वापस नहीं कर सकता है। कोडेक केवल उन प्रारूपों का समर्थन करेगा जो यह सरणी में निर्दिष्ट हैं।

उपलब्ध प्रारूपों की सरणी चलाएं और सर्वश्रेष्ठ चुनें। यदि आप भाग्यशाली हैं, तो यह वही सटीक है जिसे आप वास्तव में चाहते हैं और sws_scale फ़ंक्शन को पिक्सेल प्रारूप रूपांतरण नहीं करना पड़ेगा। (यदि, अतिरिक्त रूप से, आप तस्वीर को स्केल या फसल करने का अनुरोध नहीं करते हैं, तो sws_scale को यह पहचानना चाहिए कि रूपांतरण एक नोप है।)

+1

पीएस ओवरराइडिंग कॉलबैक में चिपकने वाला स्थान 'avcodec_open' से पहले होगा। आपको याद है, यह थोड़ी देर हो गया है क्योंकि मैंने इस सामान को देखा था। – Kaz

+0

धन्यवाद, कज़! – kochedykov