tstools封装H264+aac成TS文件

来源:互联网 发布:淘宝子账号无锡认证 编辑:程序博客网 时间:2024/05/16 14:10

本例修改Tstools的esmerge.c示例 部分更改库内容,完成读取H264文件和AAC文件封装成TS文件。 

使用函数指针做参数传递,达到把读取源文件和写目标文件方法提到更好操作的地方。


1. 下载tstools源码

    官方网站: http://tstool.sourceforge.net/

    CSDN资源下载:http://download.csdn.net/download/u011298831/9596746


2. 编译

    源码编译时我出现了错误

    - LIBOPTS = -L$(LIBDIR) -ltstools $(ARCH_FLAGS)

   + LIBOPTS = -L$(LIBDIR) -ltstools $(ARCH_FLAGS) -lm

   修改Makefile之后即可正常编译


3. 参照esmerge.c添加自己的esmerge_plus.c

    Makefile中参考esmerge的方法添加esmerge_plus.c的方法

      $(OBJDIR)/esmerge.o \
    +$(OBJDIR)/esmerge_plus.o \


      $(BINDIR)/esmerge \
   +$(BINDIR)/esmerge_plus \


    $(BINDIR)/esmerge:$(OBJDIR)/esmerge.o $(LIB)
$(CC) $< -o $(BINDIR)/esmerge $(LDFLAGS) $(LIBOPTS)
     +$(BINDIR)/esmerge_plus:$(OBJDIR)/esmerge_plus.o $(LIB)
                $(CC) $< -o $(BINDIR)/esmerge_plus $(LDFLAGS) $(LIBOPTS)


    $(OBJDIR)/esmerge.o:     esmerge.c misc_fns.h $(ACCESSUNIT_H) $(AUDIO_H) $(TSWRITE_H) version.h
    $(CC) -c $< -o $@ $(CFLAGS)
  +$(OBJDIR)/esmerge_plus.o:     esmerge_plus.c misc_fns.h $(ACCESSUNIT_H) $(AUDIO_H) $(TSWRITE_H) version.h
    $(CC) -c $< -o $@ $(CFLAGS)


这样执行make即可获得bin\下的esmerge_plus生成文件


4. 正式修改库和esmerge_plus.c文件

    源esmerge.c文件是采用传递文件名字和文件句柄的方式,些ts目标文件也在较为深的地方,现在的目的是吧读源文件的和写目标文件提到main函数层次,方便实现read和write

    先提供main函数。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int main(int argc, char **argv)  
  2. {  
  3.     int    had_video_name = FALSE;  
  4.     int    had_audio_name = FALSE;  
  5.     int    had_output_name = FALSE;  
  6.     char  *video_name = NULL;  
  7.     char  *audio_name = NULL;  
  8.     char  *output_name = NULL;  
  9.     int    err = 0;  
  10.     ES_p   video_es = NULL;  
  11.     access_unit_context_p h264_video_context = NULL;  
  12.     avs_context_p avs_video_context = NULL;  
  13.     int    audio_file = -1;  
  14.     TS_writer_p output = NULL;  
  15.     int    quiet = FALSE;  
  16.     int    verbose = FALSE;  
  17.     int    debugging = FALSE;  
  18.     int    audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;  
  19.     int    audio_sample_rate = DAT_RATE;  
  20.     int    video_frame_rate = DEFAULT_VIDEO_FRAME_RATE;  
  21.     int    audio_type = AUDIO_ADTS;  
  22.     int    video_type = VIDEO_H264;  
  23.     int    pat_pmt_freq = 0;  
  24.     int    ii = 1;  
  25.   
  26. #if TEST_PTS_DTS  
  27.     test_pts();  
  28.     return 0;  
  29. #endif  
  30.   
  31.     if (argc < 2)  
  32.     {  
  33.         print_usage();  
  34.         return 0;  
  35.     }  
  36.   
  37.     video_type = VIDEO_H264;  
  38.     read_file = video_name = argv[1];  
  39.     audio_read_file = audio_name = argv[2];  
  40.     write_file = output_name = argv[3];  
  41.     fprintf(stderr, "### esmerge: video_name:%s \n", video_name);  
  42.     fprintf(stderr, "### esmerge: audio_name:%s \n", audio_name);  
  43.     fprintf(stderr, "### esmerge: output_name:%s\n", output_name);  
  44.   
  45.     //err = open_elementary_stream(video_name,&video_es);  
  46.     err = open_elementary_stream_ex(video_read_func, &video_es);  
  47.     if (err)  
  48.     {  
  49.         fprintf(stderr, "### esmerge: "  
  50.             "Problem starting to read video as ES - abandoning reading\n");  
  51.         return 1;  
  52.     }  
  53.   
  54.     if (video_type == VIDEO_H264)  
  55.     {  
  56.         err = build_access_unit_context(video_es, &h264_video_context);  
  57.         if (err)  
  58.         {  
  59.             fprintf(stderr, "### esmerge: "  
  60.                 "Problem starting to read video as H.264 - abandoning reading\n");  
  61.             close_elementary_stream(&video_es);  
  62.             return 1;  
  63.         }  
  64.     }  
  65.     else  
  66.     {  
  67.         fprintf(stderr, "### esmerge: Unknown video type\n");  
  68.         return 1;  
  69.     }  
  70.   
  71.     //======================================================================  
  72.     //  audio_file = open_binary_file(audio_name,FALSE);  
  73.     //  if (audio_file == -1)  
  74.     //  {  
  75.     //    fprintf(stderr,"### esmerge: "  
  76.     //            "Problem opening audio file - abandoning reading\n");  
  77.     //    close_elementary_stream(&video_es);  
  78.     //    free_access_unit_context(&h264_video_context);  
  79.     //    free_avs_context(&avs_video_context);  
  80.     //    return 1;  
  81.     //  }  
  82.     //======================================================================  
  83.   
  84.     //err = tswrite_open(TS_W_FILE,output_name,NULL,0,quiet,&output);  
  85.     err = tswrite_open_ex(TS_W_CALL, video_write_func, NULL, 0, quiet, &output);  
  86.     if (err)  
  87.     {  
  88.         fprintf(stderr, "### esmerge: "  
  89.             "Problem opening output file %s - abandoning reading\n",  
  90.             output_name);  
  91.         close_elementary_stream(&video_es);  
  92.         close_file(audio_file);  
  93.         free_access_unit_context(&h264_video_context);  
  94.         free_avs_context(&avs_video_context);  
  95.         return 1;  
  96.     }  
  97.   
  98.     switch (audio_type)  
  99.     {  
  100.     case AUDIO_ADTS:  
  101.         audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;  
  102.         break;  
  103.     default:              // hmm - or we could give up...  
  104.         audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;  
  105.         break;  
  106.     }  
  107.   
  108.     if (!quiet)  
  109.     {  
  110.         printf("Reading video from %s\n", video_name);  
  111.         printf("Writing output to  %s\n", output_name);  
  112.         printf("Video frame rate: %dHz\n", video_frame_rate);  
  113.     }  
  114.   
  115.     if (video_type == VIDEO_H264)  
  116.           
  117.         err = merge_with_h264(h264_video_context, audio_read_func, output,  
  118.         //err = merge_with_h264(h264_video_context, read_next_adts_frame, output,  
  119.         AUDIO_ADTS_MPEG2,  
  120.         audio_samples_per_frame, audio_sample_rate,  
  121.         video_frame_rate,  
  122.         pat_pmt_freq,  
  123.         quiet, verbose, debugging);  
  124.     else  
  125.     {  
  126.         printf("### esmerge: Unknown video type\n");  
  127.         return 1;  
  128.     }  
  129.     if (err)  
  130.     {  
  131.         printf("### esmerge: Error merging video and audio streams\n");  
  132.         close_elementary_stream(&video_es);  
  133.         free_access_unit_context(&h264_video_context);  
  134.         (void)tswrite_close(output, quiet);  
  135.         return 1;  
  136.     }  
  137.   
  138.     close_elementary_stream(&video_es);  
  139.     free_access_unit_context(&h264_video_context);  
  140.     err = tswrite_close(output, quiet);  
  141.     if (err)  
  142.     {  
  143.         printf("### esmerge: Error closing output %s\n", output_name);  
  144.         return 1;  
  145.     }  
  146.     return 0;  
  147. }  
本例只支持baseline/main profile的H264和-mp2adts AAC文件,读者自己根据源码做相应修改。

两个新添加的函数:

err = open_elementary_stream_ex(video_read_func, &video_es);

err = tswrite_open_ex(TS_W_CALL, video_write_func, NULL, 0, quiet, &output);


1)open_elementary_stream_ex  (es.c跟踪open_elementary_stream函数添加以下代码)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. extern int open_elementary_stream_ex(int  (*callreadfun)(char*, int),  
  2.                                   ES_p  *es)  
  3. {  
  4.   int err;  
  5.   int input;  
  6.   
  7.   input = -1;  
  8.     
  9.   err = build_elementary_stream_file_ex(callreadfun,es);  
  10.   if (err)  
  11.   {  
  12.     fprintf(stderr,"### build_elementary_stream_file_ex ");  
  13.     return 1;  
  14.   }  
  15.   return 0;  
  16. }  


同上,在相应位置添加build_elementary_stream_file_ex(es.c)方法
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.  extern int build_elementary_stream_file_ex(int  (*callreadfun)(char*, int),  
  2.                                         ES_p  *es)  
  3. {  
  4.   ES_p new = malloc(SIZEOF_ES);  
  5.   if (new == NULL)  
  6.   {  
  7.     fprintf(stderr,"### Unable to allocate elementary stream datastructure\n");  
  8.     return 1;  
  9.   }  
  10.   
  11.   new->self_input = 1;  
  12.   new->callreadfun = callreadfun;  
  13.   new->reading_ES = TRUE;  
  14.   new->input = -1;  
  15.   new->reader = NULL;  
  16.   //fprintf(stderr,"===>> setup_readahead new->callreadfun:%x\n",new->callreadfun);  
  17.   setup_readahead(new);  
  18.   
  19.   *es = new;  
  20.   return 0;  
  21. }  
这里出现两个ES_p结构原本没有的成员:self_input和callreadfun

struct elementary_stream
{
  int       reading_ES;  // TRUE if we're reading ES data direct, FALSE if PES

  +//self define read
  +int self_input;
  +int (*callreadfun)(char* data, int* len);

  ……
};

如上,在结构体elementary_stream(es_defns.h)中添加了self_input和 callreadfun,用作描述是否是个人定义的方式和传递读数据的函数方法


2)tswrite_open_ex(TS_W_CALL, video_write_func, NULL, 0, quiet, &output); (tswrite.c 跟踪tswrite_open函数添加以下代码)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. extern int tswrite_open_ex(TS_WRITER_TYPE  how,  
  2.                         void (*callfuct)(char*,int),  
  3.                         char           *multicast_if,  
  4.                         int             port,  
  5.                         int             quiet,  
  6.                         TS_writer_p    *tswriter)  
  7. {  
  8.     TS_writer_p  new;  
  9.     int err = tswrite_build(how,quiet,tswriter);  
  10.     if (err) return 1;  
  11.   
  12.     new = *tswriter;  
  13.     switch (how)  
  14.     {  
  15.     case TS_W_CALL:   
  16.         if (!quiet) printf("TS_W_CALL\n");  
  17.         new->where.callfun = callfuct;  
  18.     break;  
  19.     default:  
  20.         printf("### Unexpected writer type %d to tswrite_open()\n",how);  
  21.         free(new);  
  22.         return 1;  
  23.     }  
  24.     return 0;  
  25. }  
同1)出现TS_writer_p结构出现where.callfun新的结构
union TS_writer_output
{
  FILE   *file;
  SOCKET  socket;
  //for ts use
  +void (*callfun)(char*,int);

};

如上,在联合体TS_writer_output(tswrite_defns.h)中添加了 callfun,写数据的函数方法


读者应该对tstools有一定的熟悉,了解其工作流程。所以对tswrite_write方法 tswrite_close_file方法 static inline int get_more_data(ES_p  es)方法需要修改

下面给我我修改后的static inline int get_more_data(ES_p  es)方法(es.c文件中)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static inline int get_more_data(ES_p  es)  
  2. {  
  3.   if (es->reading_ES)  
  4.   {  
  5.     if(es->self_input == 1)  
  6.     {  
  7.         int len = 0;  
  8.         int ret = es->callreadfun(es->read_ahead,&len);  
  9.         //printf("### Error reading next bytes: %d\n",len);  
  10.         if (ret == 0)  
  11.             return EOF;  
  12.         else if (ret == -1)  
  13.         {  
  14.             printf("### Error reading next bytes: %s\n",strerror(errno));  
  15.             return 1;  
  16.         }  
  17.           
  18.         es->read_ahead_posn += es->read_ahead_len;  // length of the *last* buffer  
  19.         es->read_ahead_len = len;  
  20.         es->data = es->read_ahead;     // should be done in the setup function  
  21.         es->data_end = es->data + len; // one beyond the last byte  
  22.         es->data_ptr = es->data;  
  23.     }  
  24.     else  
  25.     {  
  26.     // Call `read` directly - we don't particularly mind if we get a "short"  
  27.     // read, since we'll just catch up later on  
  28. #ifdef _WIN32  
  29.         int len = _read(es->input,&es->read_ahead,ES_READ_AHEAD_SIZE);  
  30. #else  
  31.         ssize_t  len = read(es->input,&es->read_ahead,ES_READ_AHEAD_SIZE);  
  32. #endif  
  33.         printf("### Error reading next bytes: %d\n",len);  
  34.         if (len == 0)  
  35.             return EOF;  
  36.         else if (len == -1)  
  37.         {  
  38.             printf("### Error reading next bytes: %s\n",strerror(errno));  
  39.             return 1;  
  40.         }  
  41.   
  42.         es->read_ahead_posn += es->read_ahead_len;  // length of the *last* buffer  
  43.         es->read_ahead_len = len;  
  44.         es->data = es->read_ahead;     // should be done in the setup function  
  45.         es->data_end = es->data + len; // one beyond the last byte  
  46.         es->data_ptr = es->data;  
  47.     }  
  48.   
  49.     return 0;  
  50.   }  
  51.   else  
  52.   {  
  53.     return get_next_pes_packet(es);  
  54.   }  
  55. }  
tswrite_write方法中,为了区分出是我们新定义的方式,我们使用TS_W_CALL这个值(tswrite.c文件中)
switch (tswriter->how)

{

……

+case TS_W_CALL:
+ tswriter->where.callfun(packet,TS_PACKET_SIZE);
        +break;

……

}

tswrite_close_file方法中,为了区分出是我们新定义的方式,我们使用TS_W_CALL这个值(tswrite.c文件中)

switch (tswriter->how)

{

……

  +case TS_W_CALL:
  + break;

……

}

TS_W_CALL所加在的地方,查找TS_W_FILE即可

enum TS_writer_type
{
  TS_W_UNDEFINED,
  TS_W_STDOUT,  // standard output
  TS_W_FILE,    // a file
  TS_W_TCP,     // a socket, over TCP/IP
  TS_W_UDP,     // a socket, over UDP
  +TS_W_CALL,    // self define
};

如上,在枚举TS_writer_type(tswrite_defns.h)中添加了 TS_W_CALL


就这样,对原库代码的修改完成,回到esmerge_plus.c文件中。


3)merge_with_h264方法

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static int merge_with_h264(access_unit_context_p  video_context,  
  2.     int(*callbackfun)(char*, int*),  
  3.     TS_writer_p            output,  
  4.     int                    audio_type,  
  5.     int                    audio_samples_per_frame,  
  6.     int                    audio_sample_rate,  
  7.     int                    video_frame_rate,  
  8.     int                    pat_pmt_freq,  
  9.     int                    quiet,  
  10.     int                    verbose,  
  11.     int                    debugging)  
  12. {  
  13.     int  ii;  
  14.     int  err;  
  15.     uint32_t prog_pids[2];  
  16.     byte     prog_type[2];  
  17.   
  18.     int video_frame_count = 0;  
  19.     int audio_frame_count = 0;  
  20.   
  21.     uint32_t video_pts_increment = 90000 / video_frame_rate;  
  22.     uint32_t audio_pts_increment = (90000 * audio_samples_per_frame) / audio_sample_rate;  
  23.     uint64_t video_pts = 0;  
  24.     uint64_t audio_pts = 0;  
  25.   
  26.     // The "actual" times are just for information, so we aren't too worried  
  27.     // about accuracy - thus floating point should be OK.  
  28.     double audio_time = 0.0;  
  29.     double video_time = 0.0;  
  30.   
  31.     int got_video = TRUE;  
  32.     int got_audio = TRUE;  
  33.   
  34.     if (verbose)  
  35.         printf("Video PTS increment %u\n"  
  36.         "Audio PTS increment %u\n", video_pts_increment, audio_pts_increment);  
  37.   
  38.     // Start off our output with some null packets - this is in case the  
  39.     // reader needs some time to work out its byte alignment before it starts  
  40.     // looking for 0x47 bytes  
  41.     for (ii = 0; ii < 8; ii++)  
  42.     {  
  43.         err = write_TS_null_packet(output);  
  44.         if (err) return 1;  
  45.     }  
  46.   
  47.     // Then write some program data  
  48.     // @@@ later on we might want to repeat this every so often  
  49.     prog_pids[0] = DEFAULT_VIDEO_PID;  
  50.     prog_pids[1] = DEFAULT_AUDIO_PID;  
  51.     prog_type[0] = AVC_VIDEO_STREAM_TYPE;  
  52.   
  53.     switch (audio_type)  
  54.     {  
  55.     case AUDIO_ADTS:  
  56.     case AUDIO_ADTS_MPEG2:  
  57.     case AUDIO_ADTS_MPEG4:  
  58.         prog_type[1] = ADTS_AUDIO_STREAM_TYPE;  
  59.         break;  
  60.     case AUDIO_L2:  
  61.         prog_type[1] = MPEG2_AUDIO_STREAM_TYPE;  
  62.         break;  
  63.     case AUDIO_AC3:  
  64.         prog_type[1] = ATSC_DOLBY_AUDIO_STREAM_TYPE;  
  65.         break;  
  66.     default:              // what else can we do?  
  67.         prog_type[1] = ADTS_AUDIO_STREAM_TYPE;  
  68.         break;  
  69.     }  
  70.     err = write_TS_program_data2(output,  
  71.         1, // transport stream id  
  72.         1, // program number  
  73.         DEFAULT_PMT_PID,  
  74.         DEFAULT_VIDEO_PID,  // PCR pid  
  75.         2, prog_pids, prog_type);  
  76.     if (err)  
  77.     {  
  78.         fprintf(stderr, "### Error writing out TS program data\n");  
  79.         return 1;  
  80.     }  
  81.   
  82.     while (got_video  
  83.         || got_audio  
  84.         )  
  85.     {  
  86.         access_unit_p  access_unit;  
  87.         audio_frame_p  aframe;  
  88.   
  89.         // Start with a video frame  
  90.         if (got_video)  
  91.         {  
  92.             err = get_next_h264_frame(video_context, quiet, debugging, &access_unit);  
  93.             if (err == EOF)  
  94.             {  
  95.                 if (verbose)  
  96.                     fprintf(stderr, "EOF: no more video data\n");  
  97.                 got_video = FALSE;  
  98.             }  
  99.             else if (err)  
  100.             {  
  101.                 fprintf(stderr, "EOF: no more video data return 1;\n");  
  102.                 return 1;  
  103.             }  
  104.   
  105.         }  
  106.   
  107.         if (got_video)  
  108.         {  
  109.             video_time = video_frame_count / (double)video_frame_rate;  
  110.             video_pts += video_pts_increment;  
  111.             video_frame_count++;  
  112.             if (verbose)  
  113.                 printf("\n%s video frame %5d (@ %.2fs, " LLU_FORMAT ")\n",  
  114.                 (is_I_or_IDR_frame(access_unit) ? "**" : "++"),  
  115.                 video_frame_count, video_time, video_pts);  
  116.   
  117.             if (pat_pmt_freq && !(video_frame_count % pat_pmt_freq))  
  118.             {  
  119.                 if (verbose)  
  120.                 {  
  121.                     printf("\nwriting PAT and PMT (frame = %d, freq = %d).. ",  
  122.                         video_frame_count, pat_pmt_freq);  
  123.                 }  
  124.                 err = write_TS_program_data2(output,  
  125.                     1, // tsid  
  126.                     1, // Program number  
  127.                     DEFAULT_PMT_PID,  
  128.                     DEFAULT_VIDEO_PID, // PCR pid  
  129.                     2, prog_pids, prog_type);  
  130.             }  
  131.   
  132.   
  133.             // PCR counts frames as seen in the stream, so is easy  
  134.             // The presentation and decoding time for B frames (if we ever get any)  
  135.             // could reasonably be the same as the PCR.  
  136.             // The presentation and decoding time for I and IDR frames is unlikely to  
  137.             // be the same as the PCR (since frames come out later...), but it may  
  138.             // work to pretend the PTS is the PCR plus a delay time (for decoding)...  
  139.   
  140.             // We could output the timing information every video frame,  
  141.             // but might as well only do it on index frames.  
  142.             if (is_I_or_IDR_frame(access_unit))  
  143.                 err = write_access_unit_as_TS_with_pts_dts(access_unit, video_context,  
  144.                 output, DEFAULT_VIDEO_PID,  
  145.                 TRUE, video_pts + 45000,  
  146.                 TRUE, video_pts);  
  147.             else  
  148.                 err = write_access_unit_as_TS_with_PCR(access_unit, video_context,  
  149.                 output, DEFAULT_VIDEO_PID,  
  150.                 video_pts, 0);  
  151.             if (err)  
  152.             {  
  153.                 free_access_unit(&access_unit);  
  154.                 fprintf(stderr, "### Error writing access unit (frame)\n");  
  155.                 return 1;  
  156.             }  
  157.             free_access_unit(&access_unit);  
  158.   
  159.             // Did the logical video stream end after the last access unit?  
  160.             if (video_context->end_of_stream)  
  161.             {  
  162.                 if (verbose)  
  163.                     printf("Found End-of-stream NAL unit\n");  
  164.                 got_video = FALSE;  
  165.             }  
  166.         }  
  167.         //continue;  
  168.   
  169.         if (!got_audio || callbackfun == NULL)  
  170.             continue;  
  171.   
  172.         // Then output enough audio frames to make up to a similar time  
  173.         while (audio_pts < video_pts || !got_video)  
  174.         {  
  175.             //err = read_next_audio_frame(audio_file,audio_type,&aframe);  
  176.             char aframe_buf[1024];  
  177.             int ret = callbackfun(aframe_buf, 1024);  
  178.             fprintf(stderr, "callbackfun audio data ret:%d\n", ret);  
  179.             if (ret <= 0)  
  180.             {  
  181.                 got_audio = FALSE;  
  182.                 break;  
  183.             }  
  184.   
  185.             audio_time = audio_frame_count *  
  186.                 audio_samples_per_frame / (double)audio_sample_rate;  
  187.             audio_pts += audio_pts_increment;  
  188.             audio_frame_count++;  
  189.             if (verbose)  
  190.                 printf("** audio frame %5d (@ %.2fs, " LLU_FORMAT ")\n",  
  191.                 audio_frame_count, audio_time, audio_pts);  
  192.   
  193.             err = write_ES_as_TS_PES_packet_with_pts_dts(output, aframe_buf,  
  194.                 ret,  
  195.                 DEFAULT_AUDIO_PID,  
  196.                 DEFAULT_AUDIO_STREAM_ID,  
  197.                 TRUE, audio_pts,  
  198.                 TRUE, audio_pts);  
  199.             if (err)  
  200.             {  
  201.                 return 1;  
  202.             }  
  203.         }  
  204.     }  
  205.   
  206.     if (!quiet)  
  207.     {  
  208.         uint32_t video_elapsed = 100 * video_frame_count / video_frame_rate;  
  209.         uint32_t audio_elapsed = 100 * audio_frame_count*  
  210.             audio_samples_per_frame / audio_sample_rate;  
  211.         printf("Read %d video frame%s, %.2fs elapsed (%dm %.2fs)\n",  
  212.             video_frame_count, (video_frame_count == 1 ? "" : "s"),  
  213.             video_elapsed / 100.0, video_elapsed / 6000, (video_elapsed % 6000) / 100.0);  
  214.         printf("Read %d audio frame%s, %.2fs elapsed (%dm %.2fs)\n",  
  215.             audio_frame_count, (audio_frame_count == 1 ? "" : "s"),  
  216.             audio_elapsed / 100.0, audio_elapsed / 6000, (audio_elapsed % 6000) / 100.0);  
  217.     }  
  218.   
  219.     return 0;  
  220.   
  221. }  


然后是几个读写方法

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <fcntl.h>  
  2. int video_fd_r = -1;  
  3. int video_fd_w = -1;  
  4. int audio_fd_r = -1;  
  5.   
  6. char* read_file = NULL;  
  7. char* write_file = NULL;  
  8. char* audio_read_file = NULL;  
  9.   
  10. int video_write_func(char* data, int len)  
  11. {  
  12.     if (video_fd_w == -1)  
  13.     {  
  14.         int flags = 0;  
  15.         flags = flags | O_WRONLY | O_CREAT | O_TRUNC;  
  16.         video_fd_w = open(write_file, flags, 00777);  
  17.   
  18.         if (video_fd_w == -1)  
  19.         {  
  20.             fprintf(stderr, "### Error opening file %s %s\n", write_file, strerror(errno));  
  21.         }  
  22.         else  
  23.         {  
  24.             fprintf(stderr, "### opening file %s %d\n", write_file, video_fd_w);  
  25.         }  
  26.     }  
  27.   
  28.     int _len = write(video_fd_w, data, len);  
  29.     if (_len == len)  
  30.     {  
  31.         //fprintf(stderr,"====>>> video_write_func _len:%d len:%d\n",_len,len);  
  32.     }  
  33.     else  
  34.     {  
  35.         //fprintf(stderr,"### error write file %s %s\n","test.ts",strerror(errno));   
  36.     }  
  37.   
  38. }  
  39.   
  40. int audio_read_func(char* data, int len)  
  41. {  
  42.     if (audio_fd_r == -1)  
  43.     {  
  44.         int flags = 0;  
  45.         flags = flags | O_RDONLY;  
  46.         audio_fd_r = open(audio_read_file, flags);  
  47.   
  48.         if (audio_fd_r == -1)  
  49.         {  
  50.             fprintf(stderr, "###audio_read_func Error opening file %s %s\n", audio_read_file, strerror(errno));  
  51.         }  
  52.         else  
  53.         {  
  54.             fprintf(stderr, "###audio_read_func opening file %s %d\n", audio_read_file, audio_fd_r);  
  55.         }  
  56.     }  
  57.   
  58.     unsigned char aac_header[7];  
  59.     int true_size = 0;  
  60.   
  61.     true_size = read(audio_fd_r, aac_header, 7);  
  62.     if (true_size <= 0)  
  63.     {  
  64.         return 0;  
  65.     }  
  66.     else  
  67.     {  
  68.         int frame_length = ((aac_header[3] & 0x03) << 11) | (aac_header[4] << 3) |  
  69.                             ((unsigned)(aac_header[5] & 0xE0) >> 5);  
  70.   
  71.         int ii;  
  72.         for (ii=0; ii<6; ii++)  
  73.             data[ii] = aac_header[ii];  
  74.   
  75.         true_size = read(audio_fd_r, &(data[7]), frame_length - 7);  
  76.         return frame_length;  
  77.     }  
  78.   
  79. }  
  80.   
  81. int video_read_func(char* data, int* len)  
  82. {  
  83.     if (video_fd_r == -1)  
  84.     {  
  85.         int flags = 0;  
  86.         flags = flags | O_RDONLY;  
  87.         video_fd_r = open(read_file, flags);  
  88.   
  89.         if (video_fd_r == -1)  
  90.         {  
  91.             fprintf(stderr, "### Error opening file %s %s\n", read_file, strerror(errno));  
  92.         }  
  93.         else  
  94.         {  
  95.             fprintf(stderr, "### opening file %s %d\n", read_file, video_fd_r);  
  96.         }  
  97.     }  
  98.     *len = read(video_fd_r, data, ES_READ_AHEAD_SIZE);  
  99.     if (*len > 0)  
  100.     {  
  101.         //fprintf(stderr,"====>>> callreadfun len:%d\n",*len);  
  102.     }  
  103.     else if (*len < 0)  
  104.     {  
  105.         //fprintf(stderr,"### error read file %s %s\n","test.264",strerror(errno));   
  106.     }  
  107.     return *len;  
  108. }  


搞定!记得修改几个宏定义和初始化的值;

#define DEFAULT_VIDEO_FRAME_RATE  30

int    audio_sample_rate = DAT_RATE; //我用的是48000Hz的

最后声明:本例只支持baseline/main profile的H264和-mp2adts AAC文件,读者自己根据源码做相应修改。

附上我的源码:http://download.csdn.net/download/u011298831/9596805


转自http://blog.csdn.net/u011298831/article/details/52135937

0 0
原创粉丝点击