开发者

FFmpeg encoding in c

开发者 https://www.devze.com 2023-02-05 03:27 出处:网络
I have been working on a project about video summarization on android platfrom. and I am stuck in encoding. I think;

I have been working on a project about video summarization on android platfrom. and I am stuck in encoding. I think; first I must convert my frame into RGB Frame, then convert that RGB FRame into YUV Frame. Then encode the frame. After this operations, The output video was so weird. I think I missed something. Here is my las optimized code. Maybe someone has an experiement in this subject.

Its syntax is changed according to android ndk syntax:

jint Java_com_test_Test_encodeVideo(JNIEnv* env, jobject javaThis) 
{ 
     char *flname, *err, *info; 
     AVCodec *codec; 
     AVCodecContext *c= NULL; 
     int i,out_size, size, x, y,z, outbuf_size; 
     int frameCount=99; 
     FILE *f; 
     AVFrame *picture, *yuvFrame; 
     uint8_t *outbuf, *picture_buf; 
     PPMImage *img; 
     const char *destfilename = "/sdcard/new.mp4"; 
     int             numBytes; 
     uint8_t         *buffer; 

     av_register_all(); 
     // must be called before using avcodec lib 
     avcodec_init(); 

     // register all the codecs 
     avcodec_register_all(); 
     log_message("Video encoding\n"); 

     // find the H263 video encoder 
     codec = avcodec_find_encoder(CODEC_ID_H263); 
     if (!codec) { 
         sprintf(err, "codec not found\n"); 
         log_message(err); 
     } 

     c= avcodec_alloc_context(); 
     picture= avcodec_allo开发者_JS百科c_frame(); 
     yuvFrame= avcodec_alloc_frame(); 

     // get first ppm context. it is because I need width and height values. 
     img = getPPM("/sdcard/frame1.ppm"); 

     c->bit_rate = 400000; 
     // resolution must be a multiple of two 

     c->width = img->x; 
     c->height = img->y; 
     free(img); 
     // frames per second 
     c->time_base= (AVRational){1,25}; 
     c->gop_size = 10; // emit one intra frame every ten frames 
     //c->max_b_frames=1; 
     c->pix_fmt = PIX_FMT_YUV420P; 
     // open it 
     if (avcodec_open(c, codec) < 0){ 
    log_message("codec couldn't open"); 
    return -1; 
     } 
     //destfilename = (*env)->GetStringUTFChars(env, dst, 0); 
     f = fopen(destfilename, "wb"); 
     log_message(destfilename); 
     if (!f) { 
         sprintf(err, "could not open %s", destfilename); 
         log_message(err); 
     } 

     log_message("after destination file opening"); 
     // alloc image and output buffer 
     outbuf_size = 100000; 
     outbuf = malloc(outbuf_size); 
     size = c->width * c->height; 
     picture_buf = malloc(size * 3); // size for RGB 
     picture->data[0] = picture_buf; 
     picture->data[1] = picture->data[0] + size; 
     picture->data[2] = picture->data[1] + size / 4; 
     picture->linesize[0] = c->width; 
     picture->linesize[1] = c->width / 2; 
     picture->linesize[2] = c->width / 2; 

     numBytes=avpicture_get_size(PIX_FMT_YUV420P, c->width, 
              c->height); 

     buffer=malloc(numBytes); 

          // Assign appropriate parts of buffer to image planes in FrameYUV 
     avpicture_fill((AVPicture *)yuvFrame, buffer, PIX_FMT_YUV420P, 
              c->width, c->height); 
     // encode the video 
     log_message("before for loop"); 
     for(z=1;z<frameCount;z++) { 
                         sprintf(flname,"/sdcard/frame%d.ppm",z); 
                         // read the ppm file 
                         img = getPPM(flname); 
                         picture->data[0] = img->data; 
                         // convert the rgb frame into yuv frame 
                         rgb2yuv(picture,yuvFrame,c); 
                         log_message("translation completed."); 
                         // encode the image 
                         out_size = avcodec_encode_video(c, outbuf, outbuf_size, yuvFrame); 
                         sprintf(info,"encoding frame %3d (size=%5d)\n", z, out_size); 
                         log_message(info); 
                         fwrite(outbuf, 1, out_size, f); 
                         free(img); 
     } 

     // get the delayed frames 
     for(; out_size; i++) { 
         //fflush(stdout); 
         out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); 
         sprintf(info,"write frame %3d (size=%5d)\n", i, out_size); 
             log_message(info); 
         fwrite(outbuf, 1, out_size, f); 
     } 

     // add sequence end code to have a real mpeg file 
     outbuf[0] = 0x00; 
     outbuf[1] = 0x00; 
     outbuf[2] = 0x01; 
     outbuf[3] = 0xb7; 
     fwrite(outbuf, 1, 4, f); 
     fclose(f); 
     free(picture_buf); 
     free(outbuf); 

     avcodec_close(c); 
     av_free(c); 
     av_free(picture); 
     av_free(yuvFrame); 
} 

int rgb2yuv(AVFrame *frameRGB, AVFrame *frameYUV, AVCodecContext *c) 
{ 
        char *err; 
        static struct SwsContext *img_convert_ctx; 


        log_message("conversion starts"); 
        // Convert the image into YUV format from RGB format 
        if(img_convert_ctx == NULL) { 
                int w = c->width; 
                int h = c->height; 

                img_convert_ctx = sws_getContext(w, h, PIX_FMT_RGB24,w, h, c->pix_fmt, SWS_BICUBIC,NULL, NULL, NULL); 

                if(img_convert_ctx == NULL) { 
                        sprintf(err, "Cannot initialize the conversion context!\n"); 
                        log_message(err); 
                        return -1; 
                } 
        } 
  int ret = sws_scale(img_convert_ctx,frameRGB->data, frameRGB->linesize , 0,c->height,frameYUV->data, frameYUV->linesize ); 
        return; 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消