Announcement

Collapse
No announcement yet.

problem about muxing H264 raw stream into MP4 container

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rpbear
    Junior Member
    Junior Member
    • Aug 2010
    • 1

    problem about muxing H264 raw stream into MP4 container

    Hi all,
    I use the library FFMPEG to mux a raw stream of H264(without Audio stream) into MP4 container,my code is below(It' long but I hope u would read it),problem is that the output always be the input whitout any change...Can anyone give me a tip?Thanks so much!
    Code:
    #include "avmuxer.h"
    #include <sys/stat.h>
    #include <fcntl.h>
    /* 5 seconds stream duration
    #define STREAM_DURATION   5.0
    #define STREAM_FRAME_RATE 25 
    #define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
    */
    #define STREAM_PIX_FMT PIX_FMT_YUV420P 
    
    
    AVFrame *picture;
    uint8_t *video_outbuf;
    int frame_count, video_outbuf_size;
    static int firsttime = 0;
    uint8_t *extradata;
    int FD1,FD2;
    
    int main(){
        const char                *outfile = "/mnt/test/outfile.mp4";
        AVOutputFormat             *fmt;
        AVFormatContext         *oc;
        AVStream                 *audio_st,*video_st;
        double                     audio_pts, video_pts;
        int                     i,fd,err;
        avs_un_msg_t              msg;
    //----------------------
        unlink("/mnt/test/picture");
        if((FD1 = open("/mnt/test/picture",O_WRONLY | O_CREAT,0x777)) < 0){
            PRINTF("open FD failed\n");    
            return -1;
        }
        unlink("/mnt/test/extradata");
        if((FD2 = open("/mnt/test/extradata",O_WRONLY | O_CREAT,0x777)) < 0){
            PRINTF("open FD failed\n");    
            return -1;
        }
    //----------------------
        /* initialize libavcodec, and register all codecs and formats */
        extradata = malloc(MAX_AVS_UN_MSG_EXTRA);
        unlink(outfile);
        av_register_all();
    
    
        /* auto detect the output format from the name. default is
           mpeg. */
        fmt = guess_format(NULL, outfile, NULL);
        if (!fmt) {
            printf("Could not deduce output format from file extension: using MPEG.\n");
            fmt = guess_format("mpeg", NULL, NULL);
            if (!fmt) {
                fprintf(stderr, "Could not find suitable output format\n");
                exit(1);
            }
        }
        
    
        oc = av_alloc_format_context();
        if (!oc) {
            fprintf(stderr, "Memory error\n");
            exit(1);
        }
        oc->oformat = fmt;
        
        snprintf(oc->filename, sizeof(oc->filename), "%s", outfile);
    
        video_st = NULL;
        audio_st = NULL;
    
        if (fmt->video_codec != CODEC_ID_NONE) {
            video_st = add_video_stream(oc, fmt->video_codec);
        }
        /*
        if (fmt->audio_codec != CODEC_ID_NONE) {
            audio_st = add_audio_stream(oc, fmt->audio_codec);
        }
        */
        if (av_set_parameters(oc, NULL) < 0) {
            fprintf(stderr, "Invalid output format parameters\n");
            exit(1);
        }
    
        dump_format(oc, 0, outfile, 1);
    
        if (video_st){
            open_video(oc, video_st);
        }
        //if (audio_st)
        //    open_audio(oc, audio_st);
    
        if (!(fmt->flags & AVFMT_NOFILE)) {
            if (url_fopen(&oc->pb,outfile, URL_WRONLY) < 0) {
                fprintf(stderr, "Could not open '%s'\n", outfile);
                exit(1);
            }
        }
    
        /* write the stream header, if any */
        if(av_write_header(oc) < 0){
            PRINTF("av_write_header failed\n");    
            return -1;
        }
    
        if((fd = avs_un_connect("/tmp/videosvr.sock-0")) < 0){
            PRINTF("avs_un_connect failed\n");    
            return -1;
        }
    
        if(avs_un_addclient(fd) < 0){
            PRINTF("avs_un_addclient failed\n");    
            return -1;
        }
    
    again:
        err = avs_un_recv_msg(fd,&msg);
        if(err == -1 && msg.result != MF_OK){
            PRINTF("videosvr is not ready\n");
            sleep(1);
            goto again;
        }
    
        for(;;) {
            /* compute current audio and video time */
            
            if (audio_st)
                audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
            else
                audio_pts = 0.0;
    
            if (video_st)
                video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
            else
                video_pts = 0.0;
     /*
             
            if ((!audio_st || audio_pts >= STREAM_DURATION) &&
                (!video_st || video_pts >= STREAM_DURATION))
                break;
    */
            /* write interleaved audio and video frames */
            if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
               PRINTF("write_audio_frame\n");// write_audio_frame(oc, audio_st);
            } else {
                   write_video_frame(oc, video_st,fd,&msg,1080,720);
            }
            
        }
    
        /* close each codec */
        if (video_st)
            close_video(oc, video_st);
        if (audio_st)
            ;//close_audio(oc, audio_st);
    
        /* write the trailer, if any */
        av_write_trailer(oc);
    
        /* free the streams */
        for(i = 0; i < oc->nb_streams; i++) {
            av_freep(&oc->streams[i]->codec);
            av_freep(&oc->streams[i]);
        }
    
    
        /* free the stream */
        av_free(oc);
        free(extradata);
    
        return 0;
    }
    
    
    static void write_video_frame(AVFormatContext *oc,AVStream *st,int fd,avs_un_msg_t *msg,\
                                    int width,int height){
        int out_size,ret;
        AVCodecContext *c;
        AVPacket pkt;
        c = st->codec;
    
        fill_yuv_image(picture,fd,msg,c->width,c->height);
        if(write(FD1,picture->data[0],msg->extra) > 0)
            PRINTF("write to FD1\n");
        av_init_packet(&pkt);
        
        //pkt.pts = msg->u.d4t[1];
        pkt.flags |= PKT_FLAG_KEY;
        pkt.stream_index = st->index;
        pkt.data = (uint8_t *)picture->data[0];
        pkt.size = msg->extra;//sizeof(AVPicture);
        
        ret = av_write_frame(oc,&pkt);
    
        //oc->oformat = oc->oformat->next;
        if(ret != 0){
            fprintf(stderr,"Error while writing video frame\n");    
            exit(1);
        }
        av_free_packet(&pkt);
        //frame_count++;
    }
    
    static AVStream *add_video_stream(AVFormatContext *oc, int codec_id){
        AVCodecContext *c;
        AVStream *st;
    
        st = av_new_stream(oc, 0);
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
            exit(1);
        }
    
        c = st->codec;
        c->codec_id = codec_id;
        c->codec_type = CODEC_TYPE_VIDEO;
    
        /* put sample parameters */
        c->bit_rate = 4000000;
        /* resolution must be a multiple of two */
        c->width = 1080;
        c->height = 720;
        /* time base: this is the fundamental unit of time (in seconds) in terms
           of which frame timestamps are represented. for fixed-fps content,
           timebase should be 1/framerate and timestamp increments should be
           identically 1. */
        c->time_base.den = 90000;
        c->time_base.num = 3003;
        c->gop_size = 12; /* emit one intra frame every twelve frames at most */
        c->pix_fmt = STREAM_PIX_FMT;
        if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
            /* just for testing, we also add B frames */
            c->max_b_frames = 2;
        }
        if (c->codec_id == CODEC_ID_MPEG1VIDEO){
            /* Needed to avoid using macroblocks in which some coeffs overflow.
               This does not happen with normal video, it just happens here as
               the motion of the chroma plane does not match the luma plane. */
            c->mb_decision=2;
        }
        // some formats want stream headers to be separate
        if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
            c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    
        return st;
    }
    
    static void open_video(AVFormatContext *oc, AVStream *st){
        AVCodec *codec;
        AVCodecContext *c;
    
        c = st->codec;
    
        /* find the video encoder */
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
            fprintf(stderr, "codec not found\n");
            exit(1);
        }
    
        /* open the codec */
        if (avcodec_open(c, codec) < 0) {
            fprintf(stderr, "could not open codec\n");
            exit(1);
        }
    
        video_outbuf = NULL;
        
    
        /* allocate the encoded raw picture */
        picture = my_alloc_picture(c->width,c->height);
        if (!picture) {
            fprintf(stderr, "Could not allocate picture\n");
            exit(1);
        }
    
        
    }
    
    
    static void close_video(AVFormatContext *oc, AVStream *st){
        avcodec_close(st->codec);
        av_free(picture->data[0]);
        av_free(picture);
        av_free(video_outbuf);
    }
    
    
    static int fill_yuv_image(AVFrame *pic,int fd,avs_un_msg_t *msg,int width,int height){
        int err;
        
        bzero(extradata,MAX_AVS_UN_MSG_EXTRA);
        err = avs_un_recv_msg(fd,msg);
        err = avs_un_recv_msg_extra(fd,msg,extradata);
        
        if(err > 0){
            printf("recv extradata %d\n",err);
            if(write(FD2,extradata,err) > 0)
                PRINTF("write to FD2\n");
            if(avpicture_fill((AVPicture *)pic,extradata,PIX_FMT_YUV420P,width,height) < 0){
                PRINTF("avpicture_fill failed\n");    
                return -1;
            }
        }else{
            PRINTF("avs_un_recv_msg_extra failed\n");    
            return -1;
        }
        return 0;
    }
    
    
    static AVFrame *my_alloc_picture(int width,int height){
        uint8_t *picture_buf;
        int size;
        AVFrame *picture;
        
        picture = avcodec_alloc_frame();
        if (!picture)
            return NULL;
    /*    
        size = avpicture_get_size(PIX_FMT_YUV420P, width, height);
        picture_buf = av_malloc(size);
        if (!picture_buf) {
            av_free(picture);
            return NULL;
        }
        
        avpicture_fill((AVPicture *)picture, picture_buf,
                           PIX_FMT_YUV420P,width, height);
    */    
        return picture;
    
    }
Working...
😀
🥰
🤢
😎
😡
👍
👎