Changeset 5138


Ignore:
Timestamp:
Jul 30, 2015 6:23:35 AM (9 years ago)
Author:
ming
Message:

Fixed #1861: Add support for video capture orientation on Android

Location:
pjproject/trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/config_site_sample.h

    r4984 r5138  
    392392    /* Fine tune Speex's default settings for best performance/quality */ 
    393393    #define PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY 5 
     394     
     395    /* Increase number of video device's supported formats */ 
     396    #define PJMEDIA_VID_DEV_INFO_FMT_CNT        128 
    394397 
    395398    /* 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/android_dev.c

    r5003 r5138  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    1818 */ 
     19#include "util.h" 
    1920#include <pjmedia-videodev/videodev_imp.h> 
    2021#include <pj/assert.h> 
     
    3940#define ALIGN16(x)              ((((x)+15) >> 4) << 4) 
    4041 
     42/* Define whether we should maintain the aspect ratio when rotating the image. 
     43 * For more details, please refer to util.h. 
     44 */ 
     45#define MAINTAIN_ASPECT_RATIO   PJ_TRUE 
    4146 
    4247/* Format map info */ 
     
    119124    /** NV21/YV12 -> I420 Conversion buffer  */ 
    120125    pj_uint8_t             *convert_buf; 
     126    pjmedia_rect_size       cam_size; 
     127     
     128    /** Converter to rotate frame  */ 
     129    pjmedia_vid_dev_conv    conv; 
    121130     
    122131    /** Frame format param for NV21/YV12 -> I420 conversion */ 
     
    512521        vdi->dir = PJMEDIA_DIR_CAPTURE; 
    513522        vdi->has_callback = PJ_TRUE; 
    514         vdi->caps = PJMEDIA_VID_DEV_CAP_SWITCH; 
     523        vdi->caps = PJMEDIA_VID_DEV_CAP_SWITCH | 
     524                    PJMEDIA_VID_DEV_CAP_ORIENTATION; 
    515525 
    516526        /* Set driver & name info */ 
     
    579589 
    580590                for (k = 0; k < adi->sup_size_cnt && 
    581                             vdi->fmt_cnt < max_fmt_cnt; k++) 
     591                            vdi->fmt_cnt < max_fmt_cnt-1; k++) 
    582592                { 
     593                    /* Landscape video */ 
    583594                    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++], 
    584595                                              fmt, 
    585596                                              adi->sup_size[k].w, 
    586597                                              adi->sup_size[k].h, 
     598                                              DEFAULT_FPS, 1); 
     599                    /* Portrait video */ 
     600                    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++], 
     601                                              fmt, 
     602                                              adi->sup_size[k].h, 
     603                                              adi->sup_size[k].w, 
    587604                                              DEFAULT_FPS, 1); 
    588605                } 
     
    599616                adi->forced_i420 = PJ_TRUE; 
    600617                for (k = 0; k < adi->sup_size_cnt && 
    601                             vdi->fmt_cnt < max_fmt_cnt; k++) 
     618                            vdi->fmt_cnt < max_fmt_cnt-1; k++) 
    602619                { 
    603620                    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++], 
     
    605622                                              adi->sup_size[k].w, 
    606623                                              adi->sup_size[k].h, 
     624                                              DEFAULT_FPS, 1); 
     625                    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++], 
     626                                              PJMEDIA_FORMAT_I420, 
     627                                              adi->sup_size[k].h, 
     628                                              adi->sup_size[k].w, 
    607629                                              DEFAULT_FPS, 1); 
    608630                } 
     
    637659    for (i = 0; i < f->dev_count; i++) { 
    638660        and_dev_info *adi = &f->dev_info[i]; 
    639         char tmp_str[1024], *p; 
     661        char tmp_str[2048], *p; 
    640662        int j, plen, slen; 
    641663        PJ_LOG(4, (THIS_FILE, "%2d: %s", i, f->dev_info[i].info.name)); 
     
    793815 
    794816    /* Instantiate PjCamera */ 
     817    strm->cam_size.w = (vfd->size.w > vfd->size.h? vfd->size.w: vfd->size.h); 
     818    strm->cam_size.h = (vfd->size.w > vfd->size.h? vfd->size.h: vfd->size.w); 
    795819    jcam = (*jni_env)->NewObject(jni_env, jobjs.cam.cls, jobjs.cam.m_init, 
    796820                                 adi->dev_idx,          /* idx */ 
    797                                  vfd->size.w,           /* w */ 
    798                                  vfd->size.h,           /* h */ 
     821                                 strm->cam_size.w,      /* w */ 
     822                                 strm->cam_size.h,      /* h */ 
    799823                                 and_fmt,               /* fmt */ 
    800824                                 vfd->fps.num*1000/ 
     
    814838        status = PJMEDIA_EVID_SYSERR; 
    815839        goto on_return; 
     840    } 
     841     
     842    /* Video orientation. 
     843     * If we send in portrait, we need to set up orientation converter 
     844     * as well. 
     845     */ 
     846    if ((param->flags & PJMEDIA_VID_DEV_CAP_ORIENTATION) || 
     847        (vfd->size.h > vfd->size.w)) 
     848    { 
     849        if (param->orient == PJMEDIA_ORIENT_UNKNOWN) 
     850            param->orient = PJMEDIA_ORIENT_NATURAL; 
     851        and_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_ORIENTATION, 
     852                           &param->orient); 
    816853    } 
    817854 
     
    922959        } 
    923960 
     961        case PJMEDIA_VID_DEV_CAP_ORIENTATION: 
     962        { 
     963            pjmedia_orient orient = *(pjmedia_orient *)pval; 
     964 
     965            pj_assert(orient >= PJMEDIA_ORIENT_UNKNOWN && 
     966                      orient <= PJMEDIA_ORIENT_ROTATE_270DEG); 
     967 
     968            if (orient == PJMEDIA_ORIENT_UNKNOWN) 
     969                return PJ_EINVAL; 
     970 
     971            pj_memcpy(&strm->param.orient, pval, 
     972                      sizeof(strm->param.orient)); 
     973 
     974            if (!strm->conv.conv) { 
     975                status = pjmedia_vid_dev_conv_create_converter( 
     976                                                 &strm->conv, strm->pool, 
     977                                                 &strm->param.fmt, 
     978                                                 strm->cam_size, 
     979                                                 strm->param.fmt.det.vid.size, 
     980                                                 PJ_TRUE, 
     981                                                 MAINTAIN_ASPECT_RATIO); 
     982                 
     983                if (status != PJ_SUCCESS) 
     984                    return status; 
     985            } 
     986             
     987            pjmedia_vid_dev_conv_set_rotation(&strm->conv, strm->param.orient); 
     988             
     989            PJ_LOG(4, (THIS_FILE, "Video capture orientation set to %d", 
     990                                  strm->param.orient)); 
     991 
     992            break; 
     993        } 
     994 
    924995        default: 
    925996            status = PJMEDIA_EVID_INVCAP; 
     
    10061077    jni_detach_env(with_attach); 
    10071078     
     1079    pjmedia_vid_dev_conv_destroy_converter(&strm->conv); 
     1080     
    10081081    if (strm->pool) 
    10091082        pj_pool_release(strm->pool); 
     
    10211094    pjmedia_frame f; 
    10221095    pj_uint8_t *Y, *U, *V; 
     1096    pj_status_t status;  
     1097    void *frame_buf, *data_buf;      
    10231098 
    10241099    strm->frame_ts.u64 += strm->ts_inc; 
     
    10401115    f.size = length; 
    10411116    f.timestamp.u64 = strm->frame_ts.u64; 
    1042     f.buf = (*env)->GetByteArrayElements(env, data, 0); 
     1117    f.buf = data_buf = (*env)->GetByteArrayElements(env, data, 0); 
    10431118 
    10441119    Y = (pj_uint8_t*)f.buf; 
     
    11161191        } 
    11171192    } 
     1193     
     1194    status = pjmedia_vid_dev_conv_resize_and_rotate(&strm->conv,  
     1195                                                    f.buf, 
     1196                                                    &frame_buf); 
     1197    if (status == PJ_SUCCESS) { 
     1198        f.buf = frame_buf; 
     1199    } 
    11181200 
    11191201    (*strm->vid_cb.capture_cb)(&strm->base, strm->user_data, &f); 
    1120     (*env)->ReleaseByteArrayElements(env, data, f.buf, JNI_ABORT); 
     1202    (*env)->ReleaseByteArrayElements(env, data, data_buf, JNI_ABORT); 
    11211203} 
    11221204 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/ios_dev.m

    r5118 r5138  
    4040 
    4141/* Define whether we should maintain the aspect ratio when rotating the image. 
    42  * For more details, please refer to vid_util.h. 
     42 * For more details, please refer to util.h. 
    4343 */ 
    44 #define MAINTAIN_ASPECT_RATIO PJ_TRUE 
     44#define MAINTAIN_ASPECT_RATIO   PJ_TRUE 
    4545 
    4646typedef struct ios_fmt_info 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/util.c

    r5118 r5138  
    169169    pjmedia_vid_dev_conv_set_rotation(conv, PJMEDIA_ORIENT_NATURAL); 
    170170 
    171     PJ_LOG(4, (THIS_FILE, "Orientation converter created: %dx%d to %dx%d", 
     171    PJ_LOG(4, (THIS_FILE, "Orientation converter created: %dx%d to %dx%d, " 
     172                          "maintain aspect ratio=%s", 
    172173                          conv_param.src.det.vid.size.w, 
    173174                          conv_param.src.det.vid.size.h, 
    174175                          conv_param.dst.det.vid.size.w, 
    175                           conv_param.dst.det.vid.size.h)); 
     176                          conv_param.dst.det.vid.size.h, 
     177                          maintain_aspect_ratio? "yes": "no")); 
    176178                           
    177179    return PJ_SUCCESS; 
  • pjproject/trunk/pjsip-apps/src/swig/java/android/AndroidManifest.xml

    r4997 r5138  
    4141        <activity 
    4242            android:name="org.pjsip.pjsua2.app.CallActivity" 
     43            android:configChanges="orientation|keyboardHidden|screenSize" 
    4344            android:label="@string/title_activity_call" > 
    4445        </activity> 
  • pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java

    r5102 r5138  
    2222import android.os.Handler; 
    2323import android.os.Message; 
     24import android.view.Display; 
     25import android.view.Surface; 
    2426import android.view.SurfaceHolder; 
    2527import android.view.SurfaceView; 
    2628import android.view.View; 
     29import android.view.WindowManager; 
    2730import android.widget.Button; 
    2831import android.widget.TextView; 
    2932import android.app.Activity; 
     33import android.content.Context; 
     34import android.content.res.Configuration; 
    3035 
    3136import org.pjsip.pjsua2.*; 
     
    132137 
    133138    @Override 
     139    public void onConfigurationChanged(Configuration newConfig) { 
     140        super.onConfigurationChanged(newConfig); 
     141         
     142        WindowManager wm; 
     143        Display display; 
     144        int rotation; 
     145        pjmedia_orient orient; 
     146 
     147        wm = (WindowManager)this.getSystemService(Context.WINDOW_SERVICE); 
     148        display = wm.getDefaultDisplay(); 
     149        rotation = display.getRotation(); 
     150        System.out.println("Device orientation changed: " + rotation); 
     151         
     152        switch (rotation) { 
     153        case Surface.ROTATION_0:   // Portrait 
     154            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_270DEG; 
     155            break; 
     156        case Surface.ROTATION_90:  // Landscape, home button on the right 
     157            orient = pjmedia_orient.PJMEDIA_ORIENT_NATURAL; 
     158            break; 
     159        case Surface.ROTATION_180: 
     160            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_90DEG; 
     161            break; 
     162        case Surface.ROTATION_270: // Landscape, home button on the left 
     163            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_180DEG; 
     164            break; 
     165        default: 
     166            orient = pjmedia_orient.PJMEDIA_ORIENT_UNKNOWN; 
     167        } 
     168 
     169        if (MyApp.ep != null && MainActivity.account != null) { 
     170            try { 
     171                AccountConfig cfg = MainActivity.account.cfg; 
     172                int cap_dev = cfg.getVideoConfig().getDefaultCaptureDevice(); 
     173                MyApp.ep.vidDevManager().setCaptureOrient(cap_dev, orient, 
     174                                                          true); 
     175            } catch (Exception e) { 
     176                System.out.println(e); 
     177            } 
     178        } 
     179    }     
     180 
     181    @Override 
    134182    protected void onDestroy() 
    135183    { 
     
    256304 
    257305            if (MainActivity.currentCall.vidWin != null) { 
     306                /* Set capture orientation according to current 
     307                 * device orientation. 
     308                 */ 
     309                onConfigurationChanged(getResources().getConfiguration()); 
    258310                /* If there's incoming video, display it. */ 
    259311                setupVideoSurface(); 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.i

    r5123 r5138  
    9494typedef enum pjmedia_tp_proto {PJMEDIA_TP_PROTO_NONE = 0, PJMEDIA_TP_PROTO_RTP_AVP, PJMEDIA_TP_PROTO_RTP_SAVP, PJMEDIA_TP_PROTO_UNKNOWN} pjmedia_tp_proto; 
    9595 
     96typedef enum pjmedia_orient {PJMEDIA_ORIENT_UNKNOWN, PJMEDIA_ORIENT_NATURAL, PJMEDIA_ORIENT_ROTATE_90DEG, PJMEDIA_ORIENT_ROTATE_180DEG, PJMEDIA_ORIENT_ROTATE_270DEG} pjmedia_orient; 
     97 
    9698typedef enum pjmedia_format_id {PJMEDIA_FORMAT_L16 = 0, PJMEDIA_FORMAT_PCM = PJMEDIA_FORMAT_L16, PJMEDIA_FORMAT_PCMA = ((('W' << 24) | ('A' << 16)) | ('L' << 8)) | 'A', PJMEDIA_FORMAT_ALAW = PJMEDIA_FORMAT_PCMA, PJMEDIA_FORMAT_PCMU = ((('W' << 24) | ('A' << 16)) | ('L' << 8)) | 'u', PJMEDIA_FORMAT_ULAW = PJMEDIA_FORMAT_PCMU, PJMEDIA_FORMAT_AMR = ((('R' << 24) | ('M' << 16)) | ('A' << 8)) | ' ', PJMEDIA_FORMAT_G729 = ((('9' << 24) | ('2' << 16)) | ('7' << 8)) | 'G', PJMEDIA_FORMAT_ILBC = ((('C' << 24) | ('B' << 16)) | ('L' << 8)) | 'I', PJMEDIA_FORMAT_RGB24 = ((('3' << 24) | ('B' << 16)) | ('G' << 8)) | 'R', PJMEDIA_FORMAT_RGBA = ((('A' << 24) | ('B' << 16)) | ('G' << 8)) | 'R', PJMEDIA_FORMAT_BGRA = ((('A' << 24) | ('R' << 16)) | ('G' << 8)) | 'B', PJMEDIA_FORMAT_RGB32 = PJMEDIA_FORMAT_RGBA, PJMEDIA_FORMAT_DIB = (((' ' << 24) | ('B' << 16)) | ('I' << 8)) | 'D', PJMEDIA_FORMAT_GBRP = ((('P' << 24) | ('R' << 16)) | ('B' << 8)) | 'G', PJMEDIA_FORMAT_AYUV = ((('V' << 24) | ('U' << 16)) | ('Y' << 8)) | 'A', PJMEDIA_FORMAT_YUY2 = ((('2' << 24) | ('Y' << 16)) | ('U' << 8)) | 'Y', PJMEDIA_FORMAT_UYVY = ((('Y' << 24) | ('V' << 16)) | ('Y' << 8)) | 'U', PJMEDIA_FORMAT_YVYU = ((('U' << 24) | ('Y' << 16)) | ('V' << 8)) | 'Y', PJMEDIA_FORMAT_I420 = ((('0' << 24) | ('2' << 16)) | ('4' << 8)) | 'I', PJMEDIA_FORMAT_IYUV = PJMEDIA_FORMAT_I420, PJMEDIA_FORMAT_YV12 = ((('2' << 24) | ('1' << 16)) | ('V' << 8)) | 'Y', PJMEDIA_FORMAT_NV21 = ((('1' << 24) | ('2' << 16)) | ('V' << 8)) | 'N', PJMEDIA_FORMAT_I422 = ((('2' << 24) | ('2' << 16)) | ('4' << 8)) | 'I', PJMEDIA_FORMAT_I420JPEG = ((('0' << 24) | ('2' << 16)) | ('4' << 8)) | 'J', PJMEDIA_FORMAT_I422JPEG = ((('2' << 24) | ('2' << 16)) | ('4' << 8)) | 'J', PJMEDIA_FORMAT_H261 = ((('1' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_H263 = ((('3' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_H263P = ((('3' << 24) | ('6' << 16)) | ('2' << 8)) | 'P', PJMEDIA_FORMAT_H264 = ((('4' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_MJPEG = ((('G' << 24) | ('P' << 16)) | ('J' << 8)) | 'M', PJMEDIA_FORMAT_MPEG1VIDEO = ((('V' << 24) | ('1' << 16)) | ('P' << 8)) | 'M', PJMEDIA_FORMAT_MPEG2VIDEO = ((('V' << 24) | ('2' << 16)) | ('P' << 8)) | 'M', PJMEDIA_FORMAT_MPEG4 = ((('4' << 24) | ('G' << 16)) | ('P' << 8)) | 'M'} pjmedia_format_id; 
    9799 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.lst

    r5123 r5138  
    1515pjmedia/wav_port.h              pjmedia_file_writer_option pjmedia_file_player_option 
    1616pjmedia/tonegen.h               pjmedia_tone_digit pjmedia_tone_digit_map pjmedia_tone_desc 
    17 pjmedia/types.h                 pjmedia_type pjmedia_dir pjmedia_tp_proto 
     17pjmedia/types.h                 pjmedia_type pjmedia_dir pjmedia_tp_proto pjmedia_orient 
    1818pjmedia/format.h                pjmedia_format_id 
    1919 
  • pjproject/trunk/pjsip/include/pjsua2/media.hpp

    r5123 r5138  
    16741674    const VideoDevInfoVector &enumDev() throw(Error); 
    16751675 
     1676    /** 
     1677     * Check whether the video capture device is currently active, i.e. if 
     1678     * a video preview has been started or there is a video call using 
     1679     * the device.     
     1680     * 
     1681     * @param dev_id    The video device id 
     1682     *  
     1683     * @return          True if it's active. 
     1684     */ 
     1685    bool isCaptureActive(int dev_id) const; 
     1686 
     1687    /** 
     1688     * This will configure video orientation of the video capture device. 
     1689     * If the device is currently active (i.e. if there is a video call 
     1690     * using the device or a video preview has been started), the method 
     1691     * will forward the setting to the video device instance to be applied 
     1692     * immediately, if it supports it. 
     1693     * 
     1694     * The setting will be saved for future opening of the video device, 
     1695     * if the "keep" argument is set to true. If the video device is 
     1696     * currently inactive, and the "keep" argument is false, this method 
     1697     * will throw Error. 
     1698     * 
     1699     * @param dev_id    The video device id 
     1700     * @param orient    The video orientation. 
     1701     * @param keep      Specify whether the setting is to be kept for 
     1702     *                  future use. 
     1703     * 
     1704     */ 
     1705    void setCaptureOrient(pjmedia_vid_dev_index dev_id, 
     1706                          pjmedia_orient orient, 
     1707                          bool keep=true) throw(Error); 
     1708 
    16761709private: 
    16771710    VideoDevInfoVector videoDevList; 
  • pjproject/trunk/pjsip/src/pjsua2/media.cpp

    r5123 r5138  
    13071307} 
    13081308 
     1309bool VidDevManager::isCaptureActive(int dev_id) const 
     1310{ 
     1311#if PJSUA_HAS_VIDEO 
     1312    return (pjsua_vid_dev_is_active(dev_id) == PJ_TRUE? true: false); 
     1313#else 
     1314    PJ_UNUSED_ARG(dev_id); 
     1315     
     1316    return false; 
     1317#endif 
     1318} 
     1319     
     1320void VidDevManager::setCaptureOrient(pjmedia_vid_dev_index dev_id, 
     1321                                     pjmedia_orient orient, 
     1322                                     bool keep) throw(Error) 
     1323{ 
     1324#if PJSUA_HAS_VIDEO 
     1325    PJSUA2_CHECK_EXPR(pjsua_vid_dev_set_setting(dev_id, 
     1326                          PJMEDIA_VID_DEV_CAP_ORIENTATION, &orient, keep)); 
     1327#endif 
     1328} 
     1329 
     1330 
    13091331VidDevManager::VidDevManager() 
    13101332{ 
Note: See TracChangeset for help on using the changeset viewer.