screenrecorder.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * 叶海辉
  3. * QQ群121376426
  4. * http://blog.yundiantech.com/
  5. */
  6. #include "screenrecorder.h"
  7. #include <QDateTime>
  8. #include <QDebug>
  9. extern int audio_input_frame_size;
  10. ScreenRecorder::ScreenRecorder()
  11. {
  12. m_isRun = false;
  13. }
  14. ScreenRecorder::~ScreenRecorder()
  15. {
  16. }
  17. ErroCode ScreenRecorder::init(QString audioDevName)
  18. {
  19. AVCodec *pCodec = NULL;
  20. AVCodec *aCodec = NULL;
  21. av_register_all();
  22. avformat_network_init();
  23. avdevice_register_all(); //Register Device
  24. pFormatCtx = avformat_alloc_context();
  25. AVInputFormat *ifmt = av_find_input_format("dshow");
  26. QString audioDevOption = QString("audio=%1").arg(audioDevName);
  27. if(avformat_open_input(&pFormatCtx,audioDevOption.toUtf8(),ifmt,NULL)!=0){
  28. fprintf(stderr,"Couldn't open input stream audio.(无法打开输入流)\n");
  29. return AudioOpenFailed;
  30. }
  31. if(avformat_open_input(&pFormatCtx,"video=screen-capture-recorder",ifmt,NULL)!=0){
  32. fprintf(stderr,"Couldn't open input stream video.(无法打开输入流)\n");
  33. return VideoOpenFailed;
  34. }
  35. videoindex=-1;
  36. for(i=0; i<pFormatCtx->nb_streams; i++)
  37. if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
  38. {
  39. videoindex=i;
  40. break;
  41. }
  42. if(videoindex==-1)
  43. {
  44. printf("Didn't find a video stream.(没有找到视频流)\n");
  45. return VideoOpenFailed;
  46. }
  47. pCodecCtx = pFormatCtx->streams[videoindex]->codec;
  48. pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  49. if(pCodec == NULL)
  50. {
  51. printf("video Codec not found.\n");
  52. return VideoDecoderOpenFailed;
  53. }
  54. if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
  55. {
  56. printf("Could not open video codec.\n");
  57. return VideoDecoderOpenFailed;
  58. }
  59. audioindex = -1;
  60. aCodecCtx = NULL;
  61. for(i=0; i<pFormatCtx->nb_streams; i++)
  62. if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
  63. {
  64. audioindex=i;
  65. break;
  66. }
  67. if(audioindex==-1)
  68. {
  69. printf("Didn't find a video stream.(没有找到视频流)\n");
  70. return AudioOpenFailed;
  71. }
  72. aCodecCtx = pFormatCtx->streams[audioindex]->codec;
  73. aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
  74. if(aCodec == NULL)
  75. {
  76. printf("audio Codec not found.\n");
  77. return AudioDecoderOpenFailed;
  78. }
  79. if(avcodec_open2(aCodecCtx, aCodec,NULL)<0)
  80. {
  81. printf("Could not open video codec.\n");
  82. return AudioDecoderOpenFailed;
  83. }
  84. aFrame=avcodec_alloc_frame();
  85. pFrame=avcodec_alloc_frame();
  86. pFrameYUV=avcodec_alloc_frame();
  87. out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
  88. avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
  89. setWidth(pCodecCtx->width, pCodecCtx->height);
  90. return SUCCEED;
  91. }
  92. void ScreenRecorder::deInit()
  93. {
  94. av_free(out_buffer);
  95. av_free(aFrame);
  96. av_free(pFrame);
  97. av_free(pFrameYUV);
  98. avcodec_close(pCodecCtx);
  99. if (aCodecCtx)
  100. avcodec_close(aCodecCtx);
  101. ///下面这2个释放这里会奔溃 这里先无视 后面再完善它
  102. // avformat_close_input(&pFormatCtx);
  103. // avformat_free_context(pFormatCtx);
  104. }
  105. void ScreenRecorder::startRecord()
  106. {
  107. m_isRun = true;
  108. // m_writeFile->startWrite();
  109. startEncode();
  110. start();
  111. }
  112. void ScreenRecorder::stopRecord()
  113. {
  114. m_isRun = false;
  115. stopEncode();
  116. }
  117. void ScreenRecorder::run()
  118. {
  119. int ret, got_frame;
  120. AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
  121. // //Output Information-----------------------------
  122. // printf("File Information(文件信息)---------------------\n");
  123. // av_dump_format(pFormatCtx,0,NULL,0);
  124. // printf("-------------------------------------------------\n");
  125. struct SwsContext *img_convert_ctx;
  126. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  127. //------------------------------
  128. int y_size = pCodecCtx->width * pCodecCtx->height;
  129. int size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
  130. qint64 firstTime = QDateTime::currentMSecsSinceEpoch();
  131. while(m_isRun )
  132. {
  133. if (av_read_frame(pFormatCtx, packet)<0)
  134. {
  135. msleep(10);
  136. continue;
  137. }
  138. if(packet->stream_index==videoindex)
  139. {
  140. qint64 secondTime = QDateTime::currentMSecsSinceEpoch();
  141. if ((secondTime - firstTime) >= 100)
  142. {
  143. firstTime = secondTime;
  144. ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_frame, packet);
  145. if(ret < 0)
  146. {
  147. printf("video Decode Error.(解码错误)\n");
  148. return;
  149. }
  150. if(got_frame)
  151. {
  152. sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
  153. uint8_t * picture_buf = (uint8_t *)av_malloc(size);
  154. memcpy(picture_buf,pFrameYUV->data[0],y_size);
  155. memcpy(picture_buf+y_size,pFrameYUV->data[1],y_size/4);
  156. memcpy(picture_buf+y_size+y_size/4,pFrameYUV->data[2],y_size/4);
  157. videoDataQuene_Input(picture_buf,y_size*3/2);
  158. }
  159. }
  160. }
  161. else if(packet->stream_index == audioindex)
  162. {
  163. ret = avcodec_decode_audio4(aCodecCtx, aFrame, &got_frame, packet);
  164. if(ret < 0)
  165. {
  166. fprintf(stderr,"video Audio Error.\n");
  167. return;
  168. }
  169. if (got_frame)
  170. {
  171. int size = av_samples_get_buffer_size(NULL,aCodecCtx->channels, aFrame->nb_samples,aCodecCtx->sample_fmt, 1);
  172. int index = 0;
  173. int ONEAudioSize = audio_input_frame_size * 4;//4096
  174. for (int i=0;i<(size/ONEAudioSize);i++)
  175. {
  176. int framSize = ONEAudioSize;
  177. if (i==size/ONEAudioSize)
  178. {
  179. framSize = size%ONEAudioSize;
  180. }
  181. if (framSize<=0){
  182. break;
  183. }
  184. uint8_t * audio_buf = (uint8_t *)malloc(4096*2);
  185. memcpy(audio_buf, aFrame->data[0]+index, framSize);
  186. audioDataQuene_Input((uint8_t*)audio_buf,ONEAudioSize);
  187. index += framSize;
  188. }
  189. }
  190. }
  191. av_free_packet(packet);
  192. }
  193. qDebug()<<"record stopping...";
  194. // m_writeFile->stopWrite();
  195. qDebug()<<"record finished!";
  196. sws_freeContext(img_convert_ctx);
  197. deInit();
  198. }