Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2159817
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-08-25 10:29:57

更新版:基于ffmpeg-2.7.2

1.播放声音的代码
代码改进了一下,去掉了很多全局变量
1.1 代码
  1. cong@msi:/work/ffmpeg/test/4sound$ cat sound.c
  2. #include "utils.h"
  3. #include <libavcodec/avcodec.h>
  4. #include <libavformat/avformat.h>
  5. #include <libswscale/swscale.h>
  6. #include <libswresample/swresample.h>
  7. #include <libavutil/avstring.h>
  8. #include <libavutil/pixfmt.h>
  9. #include <libavutil/log.h>
  10. #include <SDL/SDL.h>
  11. #include <SDL/SDL_thread.h>
  12. #include <stdio.h>
  13. #include <math.h>

  14. #define SDL_AUDIO_BUFFER_SIZE 4096
  15. #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000

  16. typedef struct PacketQueue
  17. {
  18.     AVPacketList * first_pkt, *last_pkt;
  19.     int nb_packets;
  20.     int size;
  21.     SDL_mutex *mutex;
  22.     SDL_cond * cond;
  23. }PacketQueue;

  24. static int signal_quit = 0;
  25. SDL_mutex *affmutex;
  26. SDL_Event sdlevent;
  27. SDL_Thread* sdl_thread;

  28. typedef struct VideoState {
  29.     int videoindex;
  30.     int sndindex;
  31.     int frameFinished;
  32.     int wanted_freq;
  33.     int wanted_samples;
  34.     int wanted_channels;
  35.     AVFormatContext* pFormatCtx;
  36.     AVCodecContext* vdoCodecCtx;
  37.     AVCodecContext* sndCodecCtx;
  38.     AVCodec* vdoCodec;
  39.     AVCodec* sndCodec;
  40.     AVFrame* pFrame;
  41.     AVFrame* pFrameYUV;
  42.     AVPacket* packet;
  43.     struct SwsContext *img_convert_ctx;
  44.     struct SwrContext *swr_ctx;
  45.     SDL_Surface* psscreen;
  46.     SDL_Overlay* overlay;
  47.     SDL_Rect rect;

  48.     enum AVSampleFormat wanted_fmt;
  49.     int64_t wanted_channel_layout;
  50.     PacketQueue audioq;
  51.     DECLARE_ALIGNED(16,uint8_t,audio_buf2) [AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];
  52. }VideoState;

  53. static int sdl_event_thread(void* data)
  54. {
  55.     while( (0==signal_quit))
  56.     {
  57.         SDL_LockMutex(affmutex);
  58.         while(SDL_PollEvent(&sdlevent))
  59.         {
  60.             switch(sdlevent.type)
  61.             {
  62.                 case SDL_QUIT:
  63.                     {
  64.                         dbmsg("next change signal_quit to 1");
  65.                         signal_quit = 1;
  66.                     }
  67.                     break;
  68.                 default:
  69.                     break;
  70.             }
  71.         }
  72.         SDL_UnlockMutex(affmutex);
  73.     }
  74. }

  75. void packet_queue_init(PacketQueue *q)
  76. {
  77.     memset(q, 0, sizeof(PacketQueue));
  78.     q->mutex = SDL_CreateMutex();
  79.     q->cond = SDL_CreateCond();
  80. }

  81. int packet_queue_put(PacketQueue *q, AVPacket *pkt)
  82. {
  83.     AVPacketList *pkt1;
  84.     if(av_dup_packet(pkt) < 0)
  85.         return -1;
  86.     pkt1 = av_malloc(sizeof(AVPacketList));
  87.     if (!pkt1)
  88.         return -1;
  89.     pkt1->pkt = *pkt;
  90.     pkt1->next = NULL;

  91.     SDL_LockMutex(q->mutex);

  92.     if (!q->last_pkt)
  93.         q->first_pkt = pkt1;
  94.     else
  95.         q->last_pkt->next = pkt1;
  96.     q->last_pkt = pkt1;
  97.     q->nb_packets++;
  98.     q->size += pkt1->pkt.size;
  99.     SDL_CondSignal(q->cond);
  100.     SDL_UnlockMutex(q->mutex);
  101.     return 0;
  102. }

  103. static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
  104. {
  105.     AVPacketList *pkt1;
  106.     int ret;
  107.     SDL_LockMutex(q->mutex);
  108.     for(;;)
  109.     {
  110.         pkt1 = q->first_pkt;
  111.         if (pkt1)
  112.         {
  113.             q->first_pkt = pkt1->next;
  114.             if (!q->first_pkt)
  115.                 q->last_pkt = NULL;
  116.             q->nb_packets--;
  117.             q->size -= pkt1->pkt.size;
  118.             *pkt = pkt1->pkt;
  119.             av_free(pkt1);
  120.             ret = 1;
  121.             break;
  122.         } else if (!block) {
  123.             ret = 0;
  124.             break;
  125.         } else {
  126.             SDL_CondWait(q->cond, q->mutex);
  127.         }
  128.     }
  129.     SDL_UnlockMutex(q->mutex);
  130.     return ret;
  131. }

  132. int audio_decode_frame(VideoState* is)
  133. {
  134.     int i;
  135.     int len1,len2, data_size, got_frame;
  136.     int new_packet;
  137.     int64_t dec_channel_layout;
  138.     uint8_t *out[] = { is->audio_buf2 };
  139.     AVPacket *pkt = av_mallocz(sizeof(AVPacket));
  140.     AVPacket *pkt_temp = av_mallocz(sizeof(AVPacket));
  141.     AVFrame *frame = av_frame_alloc();
  142.     for(;;)
  143.     {
  144.         while(pkt_temp->size>0 || (!pkt_temp->data && new_packet))
  145.         {
  146.             if(frame)
  147.             {
  148.                 dbmsg("av_get default frame");
  149.                 av_frame_unref(frame); //reset frame
  150.             }
  151.             new_packet = 0;
  152.             len1 = avcodec_decode_audio4(is->sndCodecCtx, frame, &got_frame, pkt_temp); //decode data is store in frame
  153.             if(len1 < 0)
  154.             {
  155.                 pkt_temp->size = 0;
  156.                 break;
  157.             }
  158.             //dbmsg("len1=%d, linesize=%d",len1, frame->linesize[0]);

  159.             pkt_temp->data += len1;
  160.             pkt_temp->size -= len1;

  161.             if(got_frame <= 0) /* No data yet, get more frames */
  162.                 continue;
  163.             data_size = av_samples_get_buffer_size(NULL, is->sndCodecCtx->channels, frame->nb_samples, is->sndCodecCtx->sample_fmt, 1);
  164.             dec_channel_layout = (frame->channel_layout && frame->channels==av_get_channel_layout_nb_channels(frame->channel_layout))?
  165.                 frame->channel_layout: is->wanted_channel_layout;

  166.             dbmsg("format=%d:%d,layout=%lld:%lld,rate=%d:%d,samples=%d:%d",frame->format,is->wanted_fmt,
  167.                    (long long) dec_channel_layout,(long long)av_get_default_channel_layout(is->wanted_channels),
  168.               frame->sample_rate,is->wanted_freq,frame->nb_samples,is->wanted_samples );

  169.             dbmsg("wanted_channel_layout=%lld", (long long)is->wanted_channel_layout);
  170.             dbmsg("wanted_fmt=%d", is->wanted_fmt);
  171.             dbmsg("spec.freq=%d", is->wanted_freq);
  172.             //check: format,channel_layout,rate,sample
  173.             if((NULL==is->swr_ctx) && ( (frame->format!=is->wanted_fmt) || (dec_channel_layout!=av_get_default_channel_layout(is->wanted_channels)) ||
  174.               (frame->sample_rate!=is->wanted_freq) || (frame->nb_samples!=is->wanted_samples)) )
  175.             {
  176.                 dbmsg();
  177.                 if(is->swr_ctx != NULL)
  178.                     swr_free(&is->swr_ctx);
  179.                 dbmsg("wanted_channel_layout=%lld, wanted_fmt=%d, wanted_sample=%d, dec_channel_layout=%lld, frame->format=%d, frame->sample_rate=%d",
  180.                 (long long)is->wanted_channel_layout, is->wanted_fmt, is->wanted_samples, (long long)dec_channel_layout, frame->format, frame->sample_rate);
  181.                 is->swr_ctx = swr_alloc_set_opts(NULL, is->wanted_channel_layout, is->wanted_fmt, is->wanted_freq, dec_channel_layout, frame->format, frame->sample_rate, 0, NULL);
  182.                 if(is->swr_ctx == NULL)
  183.                 {
  184.                     dbmsg("swr_ctx == NULL");
  185.                 }
  186.                 swr_init(is->swr_ctx);
  187.                 dbmsg();
  188.             }
  189.             if(is->swr_ctx)
  190.             {
  191.                 len2 = swr_convert(is->swr_ctx, out, sizeof(is->audio_buf2)/is->wanted_channels/av_get_bytes_per_sample(frame->format),(const uint8_t **)frame->extended_data, frame->nb_samples);
  192.                 dbmsg("needed swr_onvert, len2=%d", len2);
  193.                 data_size = len2 * is->wanted_channels * av_get_bytes_per_sample(is->wanted_fmt);
  194.             }else {
  195.                 memcpy(is->audio_buf2, frame->data[0], frame->linesize[0]);
  196.             }

  197.             dbmsg("data_size =%d", data_size);
  198.             return data_size;
  199.         }
  200.         if(pkt->data)
  201.             av_free_packet(pkt);
  202.         memset(pkt_temp, 0, sizeof(*pkt_temp));
  203.         if(1 == signal_quit)
  204.             return -1;
  205.         if((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0)
  206.         {
  207.             dbmsg("get packet=%d", new_packet);
  208.             return -1;
  209.         }

  210.         *pkt_temp = *pkt;
  211.     }
  212. }

  213. void audio_callback(void *userdata, Uint8 *stream, int len)
  214. {
  215.     int i;
  216.     VideoState* is = (VideoState*)userdata;
  217.     int len1, audio_size;

  218.     static unsigned int audio_buf_size = 0;
  219.     static unsigned int audio_buf_index = 0;

  220.     while(len > 0)
  221.     {
  222.         if(audio_buf_index >= audio_buf_size)
  223.         {
  224.             audio_size = audio_decode_frame(is); //decode data is store in is->audio_buf2
  225.             //dbmsg("audio_size=%d", audio_size);
  226.             if(audio_size < 0)
  227.             {
  228.                 /* If error, output silence */
  229.                 audio_buf_size = 1024;
  230.                 memset(is->audio_buf2, 0, audio_buf_size);
  231.             } else {
  232.                 audio_buf_size = audio_size;
  233.             }
  234.             audio_buf_index = 0;
  235.         }
  236.         //dbmsg("len=%d, audio_buf_size=%d, audio_buf_index=%d", len, audio_buf_size, audio_buf_index);
  237.         len1 = audio_buf_size - audio_buf_index;
  238.         //dbmsg("len1=%d", len1);
  239.         if(len1 > len)
  240.             len1 = len;
  241.         //dbmsg("len1 = %d", len1);
  242.         memcpy(stream, (uint8_t *)is->audio_buf2 + audio_buf_index, len1);
  243.         len -= len1;
  244.         stream += len1;
  245.         audio_buf_index += len1;
  246.     }
  247. }

  248. int init_ffmpeg_and_SDL(VideoState* is, char* video_file)
  249. {
  250.     int i=0;
  251.     int ret;
  252.     SDL_AudioSpec wanted_spec, real_spec;
  253.     is->videoindex = -1;
  254.     is->sndindex = -1;
  255.     if(NULL == video_file)
  256.     {
  257.         dbmsg("input file is NULL");
  258.         return -1;
  259.     }
  260.     SDL_Init(SDL_INIT_EVERYTHING);
  261.     avcodec_register_all();
  262.     avfilter_register_all();
  263.     av_register_all();

  264.     is->pFormatCtx = avformat_alloc_context();

  265.     if(avformat_open_input(&is->pFormatCtx, video_file, NULL, NULL)!=0)
  266.         return -1;

  267.     if(avformat_find_stream_info(is->pFormatCtx, NULL)<0)
  268.         return -1;
  269.     av_dump_format(is->pFormatCtx,0, 0, 0);

  270.     for(i=0; i<is->pFormatCtx->nb_streams; i++)
  271.     {
  272.         if(is->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  273.         {
  274.             is->videoindex= i;
  275.         }
  276.         if(is->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
  277.         {
  278.             is->sndindex= i;
  279.         }
  280.     }
  281.     if(is->videoindex== -1)
  282.         dbmsg("no video stream found!");
  283.     if(is->sndindex== -1)
  284.         dbmsg("no sound stream found!");
  285.     dbmsg("videoindex=%d, sndindex=%d", is->videoindex, is->sndindex);

  286.     if(is->videoindex != -1)
  287.     {
  288.         is->vdoCodecCtx = is->pFormatCtx->streams[is->videoindex]->codec;
  289.         is->vdoCodec = avcodec_find_decoder(is->vdoCodecCtx->codec_id);
  290.         if(is->vdoCodec == NULL)
  291.         {
  292.             dbmsg("Codec not found");
  293.             return -1;
  294.         }
  295.         if(avcodec_open2(is->vdoCodecCtx, is->vdoCodec, NULL) < 0)
  296.             return -1;
  297.         is->pFrame = av_frame_alloc(); //avcodec_alloc_frame
  298.         is->pFrameYUV = av_frame_alloc();
  299.         is->img_convert_ctx = sws_getContext(is->vdoCodecCtx->width, is->vdoCodecCtx->height, is->vdoCodecCtx->pix_fmt,
  300.               is->vdoCodecCtx->width, is->vdoCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  301.         if(is->img_convert_ctx == NULL)
  302.         {
  303.             dbmsg("img_convert error");
  304.             return -1;
  305.         }
  306.         is->psscreen = SDL_SetVideoMode(is->vdoCodecCtx->width, is->vdoCodecCtx->height, 0, SDL_SWSURFACE);
  307.         SDL_WM_SetCaption( "FFMPEG Window", NULL);
  308.         is->overlay = SDL_CreateYUVOverlay(is->vdoCodecCtx->width, is->vdoCodecCtx->height, SDL_YV12_OVERLAY, is->psscreen);
  309.         is->rect.x = 0;
  310.         is->rect.y = 0;
  311.      is->rect.w = is->vdoCodecCtx->width;
  312.         is->rect.h = is->vdoCodecCtx->height;
  313.     }
  314.     if(is->sndindex != -1)
  315.     {
  316.         is->sndCodecCtx = is->pFormatCtx->streams[is->sndindex]->codec;
  317.         is->sndCodec = avcodec_find_decoder(is->sndCodecCtx->codec_id);
  318.         if(is->sndCodec == NULL)
  319.         {
  320.             dbmsg("Codec not found");
  321.             return -1;
  322.         }
  323.         if(avcodec_open2(is->sndCodecCtx, is->sndCodec, NULL) < 0)
  324.             return -1;

  325.         wanted_spec.freq = is->sndCodecCtx->sample_rate;
  326.         wanted_spec.format = AUDIO_S16SYS;
  327.         wanted_spec.channels = is->sndCodecCtx->channels;
  328.         wanted_spec.silence = 0;
  329.         wanted_spec.samples = 2048;
  330.         wanted_spec.callback = audio_callback;
  331.         wanted_spec.userdata = is;
  332.         if(SDL_OpenAudio(&wanted_spec, &real_spec) < 0)
  333.         {
  334.             dbmsg("SDL_OpenAudio:%s", SDL_GetError());
  335.             return -1;
  336.         }
  337.         //store infomation for audio swr_convert
  338.         is->wanted_fmt = AV_SAMPLE_FMT_S16; //AUDIO_S16SYS;
  339.         is->wanted_channel_layout = av_get_default_channel_layout(is->sndCodecCtx->channels);
  340.         is->wanted_freq = real_spec.freq;
  341.         is->wanted_samples = real_spec.samples;
  342.         is->wanted_channels = real_spec.channels;
  343.         dbmsg("freq=%d, channels=%d, samples=%d", is->wanted_freq, is->wanted_channels, is->wanted_samples);
  344.         packet_queue_init(&is->audioq);
  345.         SDL_PauseAudio(0);
  346.     }
  347.     return 0;
  348. }

  349. int main(int argc, char **argv)
  350. {
  351.     int ret;
  352.     VideoState* is = (VideoState*) av_mallocz(sizeof(VideoState));
  353.     if( (ret=init_ffmpeg_and_SDL(is, argv[1])) != 0)
  354.     {
  355.         dbmsg("init_ffmpeg_and SDL error");
  356.         return -1;
  357.     }
  358.     //sdl get signal quit
  359.     affmutex = SDL_CreateMutex();
  360.     sdl_thread = SDL_CreateThread(sdl_event_thread, NULL);
  361.     dbmsg("init over");
  362.     is->packet = (AVPacket*)av_malloc(sizeof(AVPacket));
  363.     while( (av_read_frame(is->pFormatCtx, is->packet)>=0) && (signal_quit==0))
  364.     {
  365.         if(is->packet->stream_index == is->videoindex)
  366.         {
  367.             if((ret=avcodec_decode_video2(is->vdoCodecCtx, is->pFrame, &is->frameFinished, is->packet)) < 0)
  368.             {
  369.                 dbmsg("decocode video error");
  370.                 return -1;
  371.             }
  372.             if(is->frameFinished)
  373.             {
  374.                 SDL_LockYUVOverlay(is->overlay);
  375.                 is->pFrameYUV->data[0] = is->overlay->pixels[0];
  376.                 is->pFrameYUV->data[1] = is->overlay->pixels[2];
  377.                 is->pFrameYUV->data[2] = is->overlay->pixels[1];
  378.                 is->pFrameYUV->linesize[0] = is->overlay->pitches[0];
  379.                 is->pFrameYUV->linesize[1] = is->overlay->pitches[2];
  380.                 is->pFrameYUV->linesize[2] = is->overlay->pitches[1];
  381.                 sws_scale(is->img_convert_ctx, (const uint8_t* const*)is->pFrame->data, is->pFrame->linesize, 0,
  382.                         is->vdoCodecCtx->height, is->pFrameYUV->data, is->pFrameYUV->linesize);
  383.                 SDL_UnlockYUVOverlay(is->overlay);
  384.                 SDL_DisplayYUVOverlay(is->overlay, &is->rect);
  385.                 SDL_Delay(40);
  386.             }
  387.         }

  388.         if(is->packet->stream_index == is->sndindex)
  389.         {
  390.             //dbmsg("next put audio");
  391.             packet_queue_put(&is->audioq, is->packet);
  392.         }
  393.     }
  394.     SDL_WaitThread(sdl_thread, &ret);
  395.     SDL_DestroyMutex(affmutex);
  396.     av_free_packet(is->packet);
  397.     av_free(is->pFrameYUV);
  398.     av_free(is->pFrame);
  399.     avcodec_close(is->vdoCodecCtx);
  400.     avcodec_close(is->sndCodecCtx);
  401.     avformat_close_input(&is->pFormatCtx);
  402.     return 0;
  403. }
  404. cong@msi:/work/ffmpeg/test/4sound$
1.2 代码打包 
4sound.rar(下载后改名为4sound.tar.gz)

阅读(1528) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~