2

ndk を使用して Android で ffmpeg を使用するために、以下に貼り付けた次の標準コード (参照: http://dranger.com/ffmpeg/ ) を使用しています。私のコードは、gcc コンパイラを使用して ubuntu 10.04 で正常に動作しています。しかし、私はアンドロイドで問題に直面しています。問題av_read_frame(pFormatCtx, &packet)は常に返されることpacket.stream_index=0です。さまざまな rtsp URL を使用してコードをテストしましたが、すべての場合で同じ動作をします。この問題以外はすべて正常に動作しているように見えるため、リンクやコンパイルの問題はありません。過去2日間からこれを解決しようとしていますが、ひどく行き詰まっています。正しい方向に向けてください。

#include <jni.h>
#include <android/log.h>

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

#include <stdio.h>
#define DEBUG_TAG "mydebug_ndk"

jint Java_com_example_tut2_MainActivity_myfunc(JNIEnv * env, jobject this,jstring myjurl) {
  AVFormatContext *pFormatCtx = NULL;
  int             i, videoStream;
  AVCodecContext  *pCodecCtx = NULL;
  AVCodec         *pCodec = NULL;
  AVFrame         *pFrame = NULL;
  AVPacket        packet;
  int             frameFinished;

  AVDictionary    *optionsDict = NULL;
  struct SwsContext *sws_ctx = NULL;

  jboolean isCopy;
  const char * mycurl = (*env)->GetStringUTFChars(env, myjurl, &isCopy);
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:p2: [%s]", mycurl);

  // Register all formats and codecs
  av_register_all();
  avformat_network_init();
  // Open video file
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_open");

  if(avformat_open_input(&pFormatCtx, mycurl, NULL, NULL)!=0)
      return -1;
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "start: %d\t%d\n",pFormatCtx->raw_packet_buffer_remaining_size,pFormatCtx->max_index_size);

  (*env)->ReleaseStringUTFChars(env, myjurl, mycurl);
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_stream");
  // Retrieve stream information
  if(avformat_find_stream_info(pFormatCtx, NULL)<0)
      return -1;
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_stream");
  // Find the first video stream
  videoStream=-1;
  for(i=0; i<pFormatCtx->nb_streams; i++)
      if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
        videoStream=i;
        break;
      }
  if(videoStream==-1)
      return -1; // Didn't find a video stream
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_videostream");
  // Get a pointer to the codec context for the video stream
  pCodecCtx=pFormatCtx->streams[videoStream]->codec;
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_codec_context");

  // Find the decoder for the video stream
  pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_decoder");

  if(pCodec==NULL)
      return -1;
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:found_decoder");

  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0)
      return -1;
  // Allocate video frame
  pFrame=avcodec_alloc_frame();
  sws_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,
        pCodecCtx->height,PIX_FMT_YUV420P,SWS_BILINEAR,NULL,NULL,NULL);
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_while");

  int count=0;
  while(av_read_frame(pFormatCtx, &packet)>=0) {
        __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "entered while: %d   %d   %d\n", packet.duration,packet.stream_index,packet.size);

      if(packet.stream_index==videoStream) {
          // Decode video frame
          //break;
          avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,&packet);
          __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:in_while");
          if(frameFinished) {
              __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:gng_out_of_while");
                break;
          }
      }

      // Free the packet that was allocated by av_read_frame
      av_free_packet(&packet);
      if(++count>1000)
         return -2; //infinite while loop
  }
  __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_while");

  // Free the YUV frame
  av_free(pFrame);
  // Close the codec
  avcodec_close(pCodecCtx);
  // Close the video file
  avformat_close_input(&pFormatCtx);

  return 0;

}
4

1 に答える 1

0

私も同じ問題を抱えています。私のテストの後、私は自分の間違いを見つけました.希望があなたを助けることができます.

私の av_read_frame() も常にストリーム インデックス 0 の av_pkg を返します。

問題は次のとおりです。ffmpeg ライブラリの 2 つのバージョンを混在させました。

以前は 0.9.x の ffmpeg をインストールしましたが、今は 1.2 の ffmpeg をインストールします

ライブラリのバージョンは異なります。0.9.x のライブラリと 1.2 のライブラリを使用しました。ということで・・・エラー発生。

私は解決策:

ffmpeg のすべてのバージョンをアンインストールしてから、ffmpeg の 1 つのバージョンを再インストールします (me->1.2)。av_read_frame() はうまくいきます。:)

于 2013-04-09T03:45:37.457 に答える