Advertisement
Guest User

Untitled

a guest
Apr 13th, 2012
528
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.86 KB | None | 0 0
  1. Android AudioRecord to FFMPEG encode native AAC
  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.media.AudioFormat;
  5. import android.media.AudioRecord;
  6. import android.media.AudioRecord.OnRecordPositionUpdateListener;
  7. import android.media.MediaRecorder;
  8. import android.os.Bundle;
  9. import android.util.Log;
  10.  
  11. public class Publisher extends Activity {
  12. private int mAudioBufferSize;
  13. private int mAudioBufferSampleSize;
  14. private AudioRecord mAudioRecord;
  15. private boolean inRecordMode = false;
  16. private short[] audioBuffer;
  17. private String Tag = "Publisher/Publisher.java";
  18.  
  19. public void onCreate(Bundle savedInstanceState) {
  20. Log.i(Tag, "|| onCreate()");
  21. super.onCreate(savedInstanceState);
  22. initAudioRecord();
  23. Log.i(Tag, "-- End onCreate()");
  24. }
  25.  
  26. @Override
  27. public void onResume() {
  28. Log.i(Tag, "|| onResume()");
  29. super.onResume();
  30. inRecordMode = true;
  31. Thread t = new Thread(new Runnable() {
  32.  
  33. public void run() {
  34. Log.i(Tag, "|| Run Threat t");
  35. getSamples();
  36. Log.i(Tag, "-- End Threat t");
  37. }
  38. });
  39. t.start();
  40. Log.i(Tag, "-- End onResume()");
  41. }
  42.  
  43. protected void onPause() {
  44. Log.i(Tag, "|| Run onPause()");
  45. inRecordMode = false;
  46. super.onPause();
  47. Log.i(Tag, "-- End onPause()");
  48. }
  49.  
  50. @Override
  51. protected void onDestroy() {
  52. Log.i(Tag, "|| Run onDestroy()");
  53. if (mAudioRecord != null) {
  54. mAudioRecord.release();
  55. Log.i(Tag + " onDestroy", "mAudioRecord.release()");
  56. }
  57. jniStopAll();
  58. super.onDestroy();
  59. android.os.Process.killProcess(android.os.Process.myPid());
  60. Log.i(Tag, "-- End onDestroy()");
  61. }
  62.  
  63. public OnRecordPositionUpdateListener mListener = new OnRecordPositionUpdateListener() {
  64.  
  65. public void onPeriodicNotification(AudioRecord recorder) {
  66. Log.i(Tag + " mListener(onPeriodicNotification)", "time is "
  67. + System.currentTimeMillis());
  68. jniSetAudioSample(audioBuffer);
  69. // audioBuffer = new short[mAudioBufferSampleSize];
  70. }
  71.  
  72. public void onMarkerReached(AudioRecord recorder) {
  73. Log.i(Tag + " mListener(onMarkerReached)",
  74. "time is " + System.currentTimeMillis());
  75. inRecordMode = false;
  76. recorder.stop();
  77. Log.i(Tag, "recorder.stop()");
  78. }
  79. };
  80.  
  81. private void initAudioRecord() {
  82. try {
  83. jniCheck();
  84. int sampleRate = 44100;
  85. int channelConfig = AudioFormat.CHANNEL_IN_MONO;
  86. int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
  87. mAudioBufferSize = 2 * AudioRecord.getMinBufferSize(sampleRate,
  88. channelConfig, audioFormat);
  89. mAudioBufferSampleSize = mAudioBufferSize / 2;
  90. Log.i(Tag, "Buffer Size " + mAudioBufferSize);
  91. Log.i(Tag, "new AudioRecord begin");
  92.  
  93. mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
  94. sampleRate, channelConfig, audioFormat, mAudioBufferSize);
  95. Log.i(Tag, "new AudioRecord end");
  96.  
  97. jniInitFFMpeg();
  98. } catch (IllegalArgumentException e) {
  99. Log.i(Tag, "initAudioRecord go Errors");
  100. e.printStackTrace();
  101. }
  102.  
  103. // mAudioRecord.setNotificationMarkerPosition(10000);
  104. mAudioRecord.setPositionNotificationPeriod(1024);
  105. mAudioRecord.setRecordPositionUpdateListener(mListener);
  106.  
  107. int audioRecordState = mAudioRecord.getState();
  108. if (audioRecordState != AudioRecord.STATE_INITIALIZED) {
  109. finish();
  110. }
  111.  
  112. }
  113.  
  114. private void getSamples() {
  115. Log.i(Tag, "|| getSamples()");
  116. if (mAudioRecord == null)
  117. return;
  118.  
  119. audioBuffer = new short[mAudioBufferSampleSize];
  120. mAudioRecord.startRecording();
  121. int audioRecordingState = mAudioRecord.getRecordingState();
  122. if (audioRecordingState != AudioRecord.RECORDSTATE_RECORDING) {
  123. finish();
  124. }
  125. while (inRecordMode) {
  126. int samplesRead = mAudioRecord.read(audioBuffer, 0,
  127. mAudioBufferSampleSize);
  128. Log.i(Tag, "getSamples >>SamplesRead : " + samplesRead);
  129. }
  130. mAudioRecord.stop();
  131. Log.i(Tag, "mAudioRecord.stop()");
  132. }
  133.  
  134. private native void jniCheck();
  135.  
  136. private native void jniInitFFMpeg();
  137.  
  138. private native void jniSetAudioSample(short[] audioBuffer);
  139.  
  140. private native void jniStopAll();
  141.  
  142. static {
  143. System.loadLibrary("ffmpeg");
  144. System.loadLibrary("testerv4");
  145.  
  146. }
  147.  
  148. }
  149.  
  150. #include <jni.h>
  151. #include <android/log.h>
  152. #include <android/bitmap.h>
  153.  
  154. #include <stdlib.h>
  155. #include <stdio.h>
  156. #include <string.h>
  157. #include <math.h>
  158. #include <sys/time.h>
  159. #include "libavformat/rtsp.h"
  160.  
  161. #include <libavutil/mathematics.h>
  162. #include <libavformat/avformat.h>
  163. #include <libavcodec/avcodec.h>
  164. #include <libswscale/swscale.h>
  165.  
  166. #undef exit
  167. /* Log System */
  168. #define LOG_TAG "FFMPEGSample - v4a"
  169. #define DEBUG_TAG "FFMPEG-AUDIO PART"
  170. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  171. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
  172.  
  173. /* 5 seconds stream duration */
  174. #define STREAM_DURATION 5.0
  175. #define STREAM_FRAME_RATE 25 /* 25 images/s */
  176. #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
  177. #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
  178. #define VIDEO_CODEC_ID CODEC_ID_FLV1
  179. #define AUDIO_CODEC_ID CODEC_ID_AAC
  180.  
  181. static int sws_flags = SWS_BICUBIC;
  182. int mode = 1; //1 = only audio, 2 = only video, 3 = both video and audio
  183.  
  184. AVFormatContext *avForCtx;
  185. //AVFormatContext *oc;
  186. AVStream *audio_st, *video_st;
  187. double audio_pts, video_pts;
  188. int frameCount, audioFrameCount, start;
  189. char *url;
  190.  
  191. /*Audio Declare*/
  192. float t, tincr, tincr2;
  193. int16_t *samples;
  194. uint8_t *audio_outbuf;
  195. int audio_outbuf_size;
  196. int audio_input_frame_size;
  197.  
  198. AVFormatContext *createAVFormatContext();
  199. AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id);
  200. void open_video(AVFormatContext *oc, AVStream *st);
  201. void open_audio(AVFormatContext *oc, AVStream *st);
  202. AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id);
  203. void write_audio_frame(AVFormatContext *oc, AVStream *st);
  204. void write_video_frame(AVFormatContext *oc, AVStream *st);
  205. void init();
  206. void setAudioSample(unsigned char *inSample[]);
  207. void stopAll();
  208.  
  209. /*/////////////////////////////////JNI Bridge////////////////////////////////////// */
  210. void Java_com_curtis_broadcaster_Publisher_Publisher_jniCheck(JNIEnv* env,
  211. jobject this) {
  212. LOGI("-@ JNI work fine @-");
  213. }
  214. void Java_com_curtis_broadcaster_Publisher_Publisher_jniInitFFMpeg(JNIEnv* env,
  215. jobject this) {
  216. LOGI("-@ Init Encorder @-");
  217.  
  218. /* initialize libavcodec, and register all codecs and formats */
  219. avcodec_init();
  220. avcodec_register_all();
  221. av_register_all();
  222. avformat_network_init(); //ERROR
  223.  
  224.  
  225. /* allocate the output media context */
  226. avForCtx = createAVFormatContext();
  227. frameCount = 1;
  228. audioFrameCount = 1;
  229. start = 0;
  230.  
  231. /* add the audio and video streams using the default format codecs
  232. and initialize the codecs */
  233. video_st = NULL;
  234. audio_st = NULL;
  235. if (mode == 1 || mode == 3) {
  236. audio_st = add_audio_stream(avForCtx, AUDIO_CODEC_ID);
  237. LOGI("(Init Encorder) - addAudioStream");
  238. }
  239. if (mode == 2 || mode == 3) {
  240. video_st = add_video_stream(avForCtx, VIDEO_CODEC_ID);
  241. LOGI("(Init Encorder) - addVideoStream");
  242.  
  243. }
  244.  
  245. // av_dump_format(avForCtx, 0, "rtsp://192.168.1.104/live/live", 1);
  246. LOGI("(Init Encorder) - Waiting to call open_*");
  247.  
  248. if (audio_st) {
  249. open_audio(avForCtx, audio_st);
  250. LOGI("(Init Encorder) - open_audio");
  251. }
  252.  
  253. if (video_st) {
  254. open_video(avForCtx, video_st);
  255. LOGI("(Init Encorder) - open_video");
  256. }
  257.  
  258. av_write_header(avForCtx);
  259. LOGI("-@ Finish Init Encorder @-");
  260.  
  261. }
  262.  
  263. void Java_com_curtis_broadcaster_Publisher_Publisher_jniSetAudioSample(
  264. JNIEnv* env, jobject this, unsigned char *inSample[]) {
  265. if (audio_st) {
  266. LOGI("-@ Start setAudioSample @-");
  267. samples = (int16_t *) inSample;
  268.  
  269. write_audio_frame(avForCtx, audio_st);
  270. LOGI("-@ Finish setAudioSample @-");
  271. }
  272. }
  273.  
  274. void Java_com_curtis_broadcaster_Publisher_Publisher_jniStopAll(JNIEnv* env,
  275. jobject this) {
  276. LOGI("-@ Stopping All @-");
  277. //close_audio(avForCtx, audio_st);
  278. //close_video(avForCtx, video_st);
  279. LOGI("-@ Stopped All @-");
  280. }
  281. /*/////////////////////////////END JNI Bridge////////////////////////////////////// */
  282.  
  283. /* New Added Coding */
  284. AVFormatContext *createAVFormatContext() {
  285. LOGI("-@OPEN - createAVFormatContext@-");
  286.  
  287. AVFormatContext *ctx = avformat_alloc_context();
  288. // ctx->oformat = av_guess_format("flv", "rtmp://192.168.1.104/live/live",
  289. // NULL);
  290. // ctx->oformat = av_guess_format("flv", NULL, NULL);
  291.  
  292. //if (!av_guess_format("flv", NULL, NULL)) {
  293.  
  294. //LOGI("-flv Can not Guess Format-");
  295. //}
  296.  
  297. ctx->oformat = av_guess_format("rtsp", NULL, NULL);
  298.  
  299. if (!av_guess_format("rtsp", NULL, NULL)) {
  300.  
  301. LOGI("-flv Can not Guess Format-");
  302. }
  303.  
  304. /*
  305. LOGI("%d",avformat_alloc_output_context2(&ctx, ctx->oformat, "flv",
  306. "rtmp://192.168.1.104/live/live"));
  307. if (!ctx) {
  308. LOGI("-@avformat_alloc_output_context2 fail@-");
  309. }*/
  310. // LOGI("flv %d",avformat_alloc_output_context2(&ctx, ctx->oformat, "flv",
  311. // "rtmp://192.168.1.104/live/live"));
  312. // LOGI("rtmp %d",avformat_alloc_output_context2(&ctx, ctx->oformat, "rtmp",
  313. // "rtmp://192.168.1.104/live/live"));
  314. // LOGI("mpeg4 %d",avformat_alloc_output_context2(&ctx, ctx->oformat, "mpeg4",
  315. // "rtmp://192.168.1.104/live/live"));
  316. // LOGI("NULL %d",avformat_alloc_output_context2(&ctx, ctx->oformat, NULL,
  317. // "rtmp://192.168.1.104/live/live"));
  318. avformat_alloc_output_context2(&ctx, ctx->oformat, "sdp",
  319. "rtsp://192.168.1.104:1935/live/live");
  320.  
  321. if (!ctx) {
  322. LOGI("-@avformat_alloc_output_context2 fail@-");
  323. }
  324.  
  325. LOGI("-@CLOSE - createAVFormatContext@-");
  326.  
  327. return ctx;
  328. }
  329.  
  330. /**************************************************************/
  331. /* audio output */
  332.  
  333. /*
  334. * add an audio output stream
  335. */
  336. AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) {
  337. LOGI("-@OPEN - add_audio_stream@-");
  338.  
  339. AVCodecContext *c;
  340. AVStream *st = avformat_new_stream(oc, avcodec_find_encoder(codec_id));
  341.  
  342. if (!st) {
  343. LOGI("-@add_audio_stream - Could not alloc stream@-");
  344. exit(1);
  345. }
  346. st->id = 1;
  347.  
  348. c = st->codec;
  349. c->codec_id = AUDIO_CODEC_ID;
  350. c->codec_type = AVMEDIA_TYPE_AUDIO;
  351.  
  352. /* put sample parameters */
  353. c->sample_fmt = AV_SAMPLE_FMT_FLT;
  354. //c->sample_fmt = AV_SAMPLE_FMT_S16;
  355. c->bit_rate = 100000;
  356. c->sample_rate = 44100;
  357. c->channels = 1;
  358.  
  359. // some formats want stream headers to be separate
  360. if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  361. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  362. LOGI("-@Close - add_audio_stream@-");
  363.  
  364. return st;
  365. }
  366.  
  367. void open_audio(AVFormatContext *oc, AVStream *st) {
  368. LOGI("@- open_audio -@");
  369.  
  370. AVCodecContext *c;
  371. AVCodec *codec;
  372.  
  373. c = st->codec;
  374. c->strict_std_compliance = -2;
  375. /* find the audio encoder */
  376. codec = avcodec_find_encoder(c->codec_id);
  377. if (!codec) {
  378. LOGI("@- open_audio E:codec not found-@");
  379. exit(1);
  380. }
  381.  
  382. /* open it */
  383. if (avcodec_open(c, codec) < 0) {
  384. LOGI("%d",avcodec_open(c, codec));
  385. LOGI("@- open_audio E:could not open codec-@");
  386. exit(1);
  387. }
  388.  
  389. /* init signal generator */
  390. t = 0;
  391. tincr = 2 * M_PI * 110.0 / c->sample_rate;
  392. /* increment frequency by 110 Hz per second */
  393. tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
  394.  
  395. audio_outbuf_size = 10000;
  396. audio_outbuf = av_malloc(audio_outbuf_size);
  397.  
  398. /* ugly hack for PCM codecs (will be removed ASAP with new PCM
  399. support to compute the input frame size in samples */
  400. if (c->frame_size <= 1) {
  401. audio_input_frame_size = audio_outbuf_size / c->channels;
  402. switch (st->codec->codec_id) {
  403. case CODEC_ID_PCM_S16LE:
  404. case CODEC_ID_PCM_S16BE:
  405. case CODEC_ID_PCM_U16LE:
  406. case CODEC_ID_PCM_U16BE:
  407. audio_input_frame_size >>= 1;
  408. break;
  409. default:
  410. break;
  411. }
  412. } else {
  413. audio_input_frame_size = c->frame_size;
  414. }
  415. LOGI("audio_input_frame_size : %d",audio_input_frame_size);
  416. samples = av_malloc(audio_input_frame_size * 2 * c->channels);
  417. LOGI("@- Close open_audio -@");
  418.  
  419. }
  420.  
  421. /* prepare a 16 bit dummy audio frame of 'frame_size' samples and
  422. 'nb_channels' channels */
  423. void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) {
  424. LOGI("@- get_audio_frame -@");
  425.  
  426. int j, i, v;
  427. int16_t *q;
  428.  
  429. q = samples;
  430. for (j = 0; j < frame_size; j++) {
  431. v = (int) (sin(t) * 10000);
  432. for (i = 0; i < nb_channels; i++)
  433. *q++ = v;
  434. t += tincr;
  435. tincr += tincr2;
  436. LOGI("@- audio_frame Looping -@");
  437. }
  438. LOGI("@- CLOSE get_audio_frame -@");
  439.  
  440. }
  441.  
  442. void write_audio_frame(AVFormatContext *oc, AVStream *st) {
  443. LOGI("@- write_audio_frame -@");
  444.  
  445. AVCodecContext *c;
  446. AVPacket pkt;
  447. av_init_packet(&pkt);
  448.  
  449. c = st->codec;
  450.  
  451. //get_audio_frame(samples, audio_input_frame_size, c->channels);
  452. LOGI("@- write_audio_frame : got frame from get_audio_frame -@");
  453.  
  454. pkt.size
  455. = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
  456. LOGI("%d",pkt.size);
  457.  
  458. if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
  459. pkt.pts
  460. = av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
  461. LOGI("%d",pkt.pts);
  462.  
  463. pkt.flags |= AV_PKT_FLAG_KEY;
  464. pkt.stream_index = st->index;
  465. pkt.data = audio_outbuf;
  466. LOGI("Finish PKT");
  467.  
  468. /* write the compressed frame in the media file */
  469. // if (av_interleaved_write_frame(oc, &pkt) != 0) {
  470. // LOGI("@- write_audio_frame E:Error while writing audio frame -@");
  471. // exit(1);
  472. // }
  473.  
  474. if (av_interleaved_write_frame(oc, &pkt) != 0) {
  475. LOGI("Error while writing audio frame %dn", audioFrameCount);
  476. } else {
  477. LOGI("Writing Audio Frame %d", audioFrameCount);
  478. }
  479.  
  480. LOGI("@- CLOSE write_audio_frame -@");
  481. audioFrameCount++;
  482. av_free_packet(&pkt);
  483. }
  484.  
  485. void close_audio(AVFormatContext *oc, AVStream *st) {
  486. avcodec_close(st->codec);
  487.  
  488. av_free(samples);
  489. av_free(audio_outbuf);
  490. }
  491.  
  492. /**************************************************************/
  493. /* video output */
  494.  
  495. AVFrame *picture, *tmp_picture;
  496. uint8_t *video_outbuf;
  497. int frame_count, video_outbuf_size;
  498.  
  499. /* add a video output stream */
  500. AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id) {
  501. AVCodecContext *c;
  502. AVStream *st;
  503. AVCodec *codec;
  504.  
  505. st = avformat_new_stream(oc, NULL);
  506. if (!st) {
  507. fprintf(stderr, "Could not alloc streamn");
  508. exit(1);
  509. }
  510.  
  511. c = st->codec;
  512.  
  513. /* find the video encoder */
  514. codec = avcodec_find_encoder(codec_id);
  515. if (!codec) {
  516. fprintf(stderr, "codec not foundn");
  517. exit(1);
  518. }
  519. avcodec_get_context_defaults3(c, codec);
  520.  
  521. c->codec_id = codec_id;
  522.  
  523. /* put sample parameters */
  524. c->bit_rate = 400000;
  525. /* resolution must be a multiple of two */
  526. c->width = 352;
  527. c->height = 288;
  528. /* time base: this is the fundamental unit of time (in seconds) in terms
  529. of which frame timestamps are represented. for fixed-fps content,
  530. timebase should be 1/framerate and timestamp increments should be
  531. identically 1. */
  532. c->time_base.den = STREAM_FRAME_RATE;
  533. c->time_base.num = 1;
  534. c->gop_size = 12; /* emit one intra frame every twelve frames at most */
  535. c->pix_fmt = STREAM_PIX_FMT;
  536. if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
  537. /* just for testing, we also add B frames */
  538. c->max_b_frames = 2;
  539. }
  540. if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
  541. /* Needed to avoid using macroblocks in which some coeffs overflow.
  542. This does not happen with normal video, it just happens here as
  543. the motion of the chroma plane does not match the luma plane. */
  544. c->mb_decision = 2;
  545. }
  546. // some formats want stream headers to be separate
  547. if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  548. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  549.  
  550. return st;
  551. }
  552.  
  553. AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) {
  554. AVFrame * picture;
  555. uint8_t *picture_buf;
  556. int size;
  557.  
  558. picture = avcodec_alloc_frame();
  559. if (!picture)
  560. return NULL;
  561. size = avpicture_get_size(pix_fmt, width, height);
  562. picture_buf = av_malloc(size);
  563. if (!picture_buf) {
  564. av_free(picture);
  565. return NULL;
  566. }
  567. avpicture_fill((AVPicture *) picture, picture_buf, pix_fmt, width, height);
  568. return picture;
  569. }
  570.  
  571. void open_video(AVFormatContext *oc, AVStream *st) {
  572. AVCodec *codec;
  573. AVCodecContext *c;
  574.  
  575. c = st->codec;
  576.  
  577. /* find the video encoder */
  578. codec = avcodec_find_encoder(c->codec_id);
  579. if (!codec) {
  580. fprintf(stderr, "codec not foundn");
  581. exit(1);
  582. }
  583.  
  584. /* open the codec */
  585. if (avcodec_open(c, codec) < 0) {
  586. fprintf(stderr, "could not open codecn");
  587. exit(1);
  588. }
  589.  
  590. video_outbuf = NULL;
  591. if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
  592. /* allocate output buffer */
  593. /* XXX: API change will be done */
  594. /* buffers passed into lav* can be allocated any way you prefer,
  595. as long as they're aligned enough for the architecture, and
  596. they're freed appropriately (such as using av_free for buffers
  597. allocated with av_malloc) */
  598. video_outbuf_size = 200000;
  599. video_outbuf = av_malloc(video_outbuf_size);
  600. }
  601.  
  602. /* allocate the encoded raw picture */
  603. picture = alloc_picture(c->pix_fmt, c->width, c->height);
  604. if (!picture) {
  605. fprintf(stderr, "Could not allocate picturen");
  606. exit(1);
  607. }
  608.  
  609. /* if the output format is not YUV420P, then a temporary YUV420P
  610. picture is needed too. It is then converted to the required
  611. output format */
  612. tmp_picture = NULL;
  613. if (c->pix_fmt != PIX_FMT_YUV420P) {
  614. tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
  615. if (!tmp_picture) {
  616. fprintf(stderr, "Could not allocate temporary picturen");
  617. exit(1);
  618. }
  619. }
  620. }
  621.  
  622. /* prepare a dummy image */
  623. void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) {
  624. int x, y, i;
  625.  
  626. i = frame_index;
  627.  
  628. /* Y */
  629. for (y = 0; y < height; y++) {
  630. for (x = 0; x < width; x++) {
  631. pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
  632. }
  633. }
  634.  
  635. /* Cb and Cr */
  636. for (y = 0; y < height / 2; y++) {
  637. for (x = 0; x < width / 2; x++) {
  638. pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
  639. pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
  640. }
  641. }
  642. }
  643.  
  644. void write_video_frame(AVFormatContext *oc, AVStream *st) {
  645. int out_size, ret;
  646. AVCodecContext *c;
  647. struct SwsContext *img_convert_ctx;
  648.  
  649. c = st->codec;
  650.  
  651. if (frame_count >= STREAM_NB_FRAMES) {
  652. /* no more frame to compress. The codec has a latency of a few
  653. frames if using B frames, so we get the last frames by
  654. passing the same picture again */
  655. } else {
  656. if (c->pix_fmt != PIX_FMT_YUV420P) {
  657. /* as we only generate a YUV420P picture, we must convert it
  658. to the codec pixel format if needed */
  659. if (img_convert_ctx == NULL) {
  660. img_convert_ctx = sws_getContext(c->width, c->height,
  661. PIX_FMT_YUV420P, c->width, c->height, c->pix_fmt,
  662. sws_flags, NULL, NULL, NULL);
  663. if (img_convert_ctx == NULL) {
  664. fprintf(stderr,
  665. "Cannot initialize the conversion contextn");
  666. exit(1);
  667. }
  668. }
  669. fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
  670. sws_scale(img_convert_ctx, tmp_picture->data,
  671. tmp_picture->linesize, 0, c->height, picture->data,
  672. picture->linesize);
  673. } else {
  674. fill_yuv_image(picture, frame_count, c->width, c->height);
  675. }
  676. }
  677.  
  678. if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  679. /* raw video case. The API will change slightly in the near
  680. future for that. */
  681. AVPacket pkt;
  682. av_init_packet(&pkt);
  683.  
  684. pkt.flags |= AV_PKT_FLAG_KEY;
  685. pkt.stream_index = st->index;
  686. pkt.data = (uint8_t *) picture;
  687. pkt.size = sizeof(AVPicture);
  688.  
  689. ret = av_interleaved_write_frame(oc, &pkt);
  690. } else {
  691. /* encode the image */
  692. out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size,
  693. picture);
  694. /* if zero size, it means the image was buffered */
  695. if (out_size > 0) {
  696. AVPacket pkt;
  697. av_init_packet(&pkt);
  698.  
  699. if (c->coded_frame->pts != AV_NOPTS_VALUE)
  700. pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base,
  701. st->time_base);
  702. if (c->coded_frame->key_frame)
  703. pkt.flags |= AV_PKT_FLAG_KEY;
  704. pkt.stream_index = st->index;
  705. pkt.data = video_outbuf;
  706. pkt.size = out_size;
  707.  
  708. /* write the compressed frame in the media file */
  709. ret = av_interleaved_write_frame(oc, &pkt);
  710. } else {
  711. ret = 0;
  712. }
  713. }
  714. if (ret != 0) {
  715. fprintf(stderr, "Error while writing video framen");
  716. exit(1);
  717. }
  718. frame_count++;
  719. }
  720.  
  721. void close_video(AVFormatContext *oc, AVStream *st) {
  722. avcodec_close(st->codec);
  723. av_free(picture->data[0]);
  724. av_free(picture);
  725. if (tmp_picture) {
  726. av_free(tmp_picture->data[0]);
  727. av_free(tmp_picture);
  728. }
  729. av_free(video_outbuf);
  730. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement