2015年10月26日

[FFMPEG]把ts串接成mp4

參考了 http://albert-oma.blogspot.tw/2013/06/ffmpeg-h264-mp4.html 這篇文章

-(void)transferToMP4
{
    NSDate *startTime = [NSDate date];
    NSDate *endTime;
    NSTimeInterval interval;
    NSLog(@"-------------------------------------");
    NSLog(@"start : %@",[NSDate date]);
    NSLog(@"-------------------------------------");
    AVBitStreamFilterContext *vbsf = NULL;
    AVBitStreamFilterContext *absf = NULL;
    AVPacket pkt;
   
    av_register_all();
    avcodec_register_all();
   
    NSString *fileName = @"export.mp4";
   
    BOOL isFirstFile = YES;
    NSString *exportPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fileName];
    if (avformat_alloc_output_context2(&outputCtx,
                                       NULL,
                                       "mp4",
                                       [exportPath UTF8String]) < 0)
    {
        NSLog(@"avformat_alloc_output_context2 : open file error!!!");
        return;
    }
   
    NSArray *fileList = [NSArray arrayWithObjects:@"http://shell.site/0006.ts",
                         @"http://shell.site/0012.ts",
                         @"http://shell.site/0018.ts", nil];
    int lastVideoPTS = 0,lastAudioPTS = 0, lastAudioDTS = 0;
    int currentLastVideoPTS = 0,currentLastAudioPTS = 0,currentLastAudioDTS = 0;
    
    for (NSString *fileName in fileList)
    {
        NSString *tsFile = fileName;
//        NSString *tsFile = [[NSBundle mainBundle] pathForResource:fileName ofType:@"ts"];
       
        //open input file
        AVFormatContext *inputCtx = NULL;
        avformat_open_input(&inputCtx,
                            [tsFile UTF8String],
                            NULL,
                            NULL);
        avformat_find_stream_info(inputCtx, NULL);
       
       
       
       
        av_dump_format(inputCtx, NULL, [tsFile UTF8String], 0);
       
        if (isFirstFile)
        {
            for (int streamIndex = 0; streamIndex < inputCtx->nb_streams; streamIndex++ )
            {
                NSLog(@"Channel %d of %d",streamIndex,inputCtx->nb_streams);
               
                AVStream *out_stream = NULL;
                AVStream *in_stream = NULL;
               
                in_stream = inputCtx->streams[streamIndex];
                out_stream = avformat_new_stream(outputCtx, in_stream->codec->codec);
                avcodec_copy_context(outputCtx->streams[streamIndex]->codec, inputCtx->streams[streamIndex]->codec);
               
                out_stream->codec->codec_tag = 0;
               
                if (outputCtx ->oformat->flags & AVFMT_GLOBALHEADER)
                {
                    out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
                }
                out_stream->time_base = in_stream->time_base;
               
            }
        }
            absf = av_bitstream_filter_init("aac_adtstoasc");
            av_dump_format(outputCtx, NULL, [exportPath UTF8String], 1);
       
        if (isFirstFile)
        {
            if (avio_open2(&outputCtx->pb,
                           [exportPath UTF8String],
                           AVIO_FLAG_WRITE,
                           &outputCtx->interrupt_callback,
                           NULL) < 0)
            {
                NSLog(@"can not open output file!!");
                return;
            }
           
            if (avformat_write_header(outputCtx, NULL) < 0)
            {
                NSLog(@"Can not write the header");
            }
        }
       
        BOOL isFirstVideoPkt = YES;
        int firstPktPTS = 0 ;
        while (1)
        {
            AVStream *in_stream = NULL;
            AVStream *out_stream = NULL;
           
            int ret = av_read_frame(inputCtx, &pkt);
           
            if (ret < 0 )
            {
                NSLog(@"read frame : %d",ret);
                break;
            }
           
            in_stream = inputCtx->streams[pkt.stream_index];
            out_stream = outputCtx->streams[pkt.stream_index];
           
           
            if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                AVPacket fpkt = pkt;
               
                pkt.data = fpkt.data;
                pkt.size = fpkt.size;
                if (isFirstVideoPkt)
                {
                    firstPktPTS = pkt.pts;
                    isFirstVideoPkt = NO;
                }
                pkt.pts = pkt.pts - firstPktPTS + lastVideoPTS;
                pkt.dts = pkt.pts;
                currentLastVideoPTS = pkt.pts;
                pkt.pos = pkt.pts;
            }
            else if (in_stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
            {
                AVPacket fpkt = pkt;
                av_bitstream_filter_filter(absf,
                                           out_stream->codec,
                                           NULL,
                                           &fpkt.data,
                                           &fpkt.size,
                                           pkt.data,
                                           pkt.size,
                                           pkt.flags & AV_PKT_FLAG_KEY);
                pkt.data = fpkt.data;
                pkt.size = fpkt.size;
               
                pkt.pts = av_rescale_q_rnd(pkt.pts + lastAudioPTS, in_stream->codec->time_base, in_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
                pkt.dts = av_rescale_q_rnd(pkt.dts + lastAudioDTS, in_stream->codec->time_base, in_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
                pkt.duration = av_rescale_q(pkt.duration, in_stream->codec->time_base, in_stream->time_base);
                currentLastAudioPTS = pkt.pts;
                currentLastAudioDTS = pkt.dts;
            }
            pkt.pos = pkt.pts;
           
            ret = av_write_frame(outputCtx, &pkt);
            if (ret < 0)
            {
                NSLog(@"write frame error!!!");
                break;
            }
           
            av_free_packet(&pkt);
        }//end while
        lastVideoPTS = currentLastVideoPTS + 1 ;
        lastAudioPTS = currentLastAudioPTS + 1;
        lastAudioDTS = currentLastAudioDTS + 1;
       
        avformat_close_input(&inputCtx);
        av_bitstream_filter_close(vbsf);
        av_bitstream_filter_close(absf);
       
        isFirstFile = NO;
    }
  
    av_write_trailer(outputCtx);
   
    avio_close(outputCtx->pb);
    avformat_free_context(outputCtx);
   
    NSLog(@"-------------------------------------");
    endTime = [NSDate date];
    NSLog(@"end : %@",endTime);
    interval = [endTime timeIntervalSinceDate:startTime];
    NSLog(@"file number:%d ,interval : %f",fileList.count,interval);
    NSLog(@"-------------------------------------");
    return;

}

沒有留言: